牛客等級之題N1(8.4場) 購物(dp動態規劃)
阿新 • • 發佈:2020-08-04
題目連結:https://ac.nowcoder.com/acm/contest/6877/A
題目描述
在遙遠的東方,有一家糖果專賣店。 這家糖果店將會在每天出售一些糖果,它每天都會生產出m個糖果,第i天的第j個糖果價格為C[i][j]元。 現在的你想要在接下來的n天去糖果店進行選購,你每天可以買多個糖果,也可以選擇不買糖果,但是最多買m個。(因為最多隻生產m個)買來糖果以後,你可以選擇吃掉糖果或者留著之後再吃。糖果不會過期,你需要保證這n天中每天你都能吃到至少一個糖果。 這家店的老闆看你經常去光顧這家店,感到非常生氣。(因為他不能好好睡覺了)於是他會額外的要求你支付點錢。具體來說,你在某一天購買了 k 個糖果,那麼你在這一天需要額外支付 k2那麼問題來了,你最少需要多少錢才能達成自己的目的呢?
輸入描述:
第一行兩個正整數n和m,分別表示天數以及糖果店每天生產的糖果數量。
接下來n行(第2行到第n+1行),每行m個正整數,第x+1行的第y個正整數表示第x天的第y個糖果的費用。
輸出描述:
輸出只有一個正整數,表示你需要支付的最小費用。
輸入
3 2 1 1 100 100 10000 10000
輸出
107
輸入
5 5 1 2 3 4 5 2 3 4 5 1 3 4 5 1 2 4 5 1 2 3 5 1 2 3 4
輸出
10
題意:輸入一個n*m的價格矩陣,表示第i天的第j個糖果的價格,我們從中選取n個,價格最低,輸出最低價格,但是我們在一天購買k個糖果就要多交k*k元。
比如樣例1的第一天,我們買2個糖果,那就要多交4元,即6元買了2個糖果,第二天我們花101買1個糖果,合計107;此外我們還要保證每一天都要有糖果吃,即第一天是肯定必須要買的
題解:初看模擬貪心,直接找最少的值,後發現模擬不出來,他可以有很多個最少的值,我們要考慮哪天買幾個,這個就比較複雜了。然後才想到dp。
我們用dp[ i ][ j ]表示 第i天 買了j個糖果的最低價格。k列舉第i天買了k個;
這裡的a[ i ][ j ]我們先預處理字首和,那樣直接加的是j-k個糖果的價格。
轉移狀態 dp[ i ][ j ] = min ( dp[ i ] [ j ] , dp [ i-1 ] [ k ] + a[ i ] [ j - k ] +( j-k )*( j-k ) )
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #include <bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn=300+7; const ll mod =998244353; int t,n,m; int ma[maxn][maxn]; int dp[maxn][maxn]; int main(){ IOS scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&ma[i][j]); } sort(ma[i]+1,ma[i]+m+1); for(int j=1;j<=m;j++){ ma[i][j]+=ma[i][j-1]; } } memset(dp,inf,sizeof(dp)); dp[0][0]=0; for(int i=1;i<=n;i++){ for(int j=i;j<=min(i*m,n);j++){ for(int k=i-1;k<=j;k++) dp[i][j]=min( dp[i][j], dp[i-1][k]+ma[i][j-k]+(j-k)*(j-k) ); } } printf("%d\n",dp[n][n]); return 0; }