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;
}


京公网安备 11010502036488号