题目链接:https://ac.nowcoder.com/acm/problem/14526
题目大意:
思路:
我们预处理每天买i个的最小费用,然后直接分组DP就可以了。有个限制:第i天至少买i个。因为每天至少吃一个。
#pragma GCC optimize(3, "Ofast", "inline")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rint register int
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
char buf[1<<20],*p1=buf,*p2=buf;
inline int read() {
int f=0,fu=1;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-')
fu=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
f=(f<<3)+(f<<1)+c-48;
c=getchar();
}
return f*fu;
}
inline void print(LL x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x >= 10)
print(x / 10);
putchar(x % 10 + '0');
}
vector<int> v[305];
vector<pair<int, int> > a[305];
int f[305][305];
int main() {
int n=read(), m=read();
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
int x=read();
v[i].push_back(x);
}
sort(v[i].begin(), v[i].end());
int w=0;
for(int j=0; j<m; j++){
w+=v[i][j];
a[i].push_back({j+1, (w+(j+1)*(j+1))});
//cout<<i<<" "<<j+1<<" "<<(w+(j+1)*(j+1))<<endl;
}
}
memset(f, 0x3f, sizeof(f));
f[0][0]=0;
for(int i=1; i<=n; i++){
for(int j=i; j<=n; j++){
for(int k=0; k<a[i].size(); k++){
int v=a[i][k].first, w=a[i][k].second;
f[i][j]=min(f[i][j], f[i-1][j]);
if(j>=v){
f[i][j]=min(f[i][j], f[i-1][j-v]+w);
}
}
}
}
printf("%d\n", f[n][n]);
return 0;
}

京公网安备 11010502036488号