dp[i][j]的状态为前i天,买了j个糖果的最小花费
题目说每天最少要有一个糖果吃,那么第i天最少要有i个糖果,最多要有min(n,im),n为天数,im为当天生产的糖果总数,
那么dp[i][j]=min(dp[i][j],dp[i-1][k]+C) k>=i-1,j>=i含义就是如果当天不选那么当天最少要有i个糖,选的话,要选几个呢?这要看i-1天选了几个。 只有我们每次都花费最小的糖果,总花费才小,所以我们可以先把每一天的花费从小到大排个序,用前缀和预处理一下。
#include<bits/stdc++.h> using namespace std; const int maxn=310; int arr[maxn][maxn]; long long dp[maxn][maxn]; long long sum[maxn][maxn]; int main(){ int n,m; cin>>n>>m; memset(sum,0,sizeof(sum)); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>arr[i][j]; } sort(arr[i]+1,arr[i]+m+1); for(int j=1;j<=m;j++){ sum[i][j]=sum[i][j-1]+arr[i][j]; } } memset(dp,0x3f,sizeof(dp)); dp[0][0]=0; for(int i=1;i<=n;i++){ for(int j=i;j<=min(n,i*m);j++){ for(int k=i-1;k<=min(n,(i-1)*m)&&k<=j;k++){ dp[i][j]=min(dp[i][j],dp[i-1][k]+sum[i][j-k]+(j-k)*(j-k)); } } } cout<<dp[n][n]; return 0; }