动态规划问题,一开始看到每天要买的糖果数还不一样,而且每个糖果还有他自己不同的价格。直接就想到了状压DP。
但本题要求花费最小,而对于某一天买k个糖果来说花费最小其实就是从价格低的糖果来买就行了。那么某一天如何选糖果的问题就这样简答的解决了。
那么状态数组为:dp[i][j]。i代表天数,j代表第到i天一共买j个糖果。值代表花费。
状态转移方程为:dp[i][j] = d[i-1][j-k]+cost(i, k)+pow(k,2);。
表示到某天一共买了j个糖果,取决于这天买了k个糖果,那么上一天就需要一共买了i-k个糖果。cost是计算这天买了k个糖果的最小花费是多少,pow(k,2)。是多余的花费。
//dp[i][j]。i代表天数,j代表第到i天一共买j个糖果。值代表花费 //状态转移方程:dp[i][j] = d[i-1][j-k]+cost(i, k)+pow(k,2); #include <bits/stdc++.h> using namespace std; #define int long long const int maxn = 300+10; int dp[maxn][maxn]; int price[maxn][maxn]; int cost(int day, int num) { int cnt = 0; for (int i=1;i<=num;i++) { cnt += price[day][i]; } return cnt; } signed main() { memset(dp, 127, sizeof dp); int n, m; cin>>n>>m; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { cin>>price[i][j]; } } for (int i=1;i<=n;i++) sort(price[i]+1, price[i]+m+1); dp[0][0] = 0; for (int i=1;i<=n;i++) { for (int j=i;j<=n;j++) { if ((i)*m<j) continue; for (int k=0;k<=j;k++) { dp[i][j] = min(dp[i][j], dp[i-1][j-k]+cost(i,k)+k*k); // cout<<"i="<<i<<" j="<<j<<endl; // cout<<"dp[i][j]="<<dp[i][j]<<endl; } } } cout<<dp[n][n]; return 0; }