题目链接: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;
}