题意:需要储备天的面包,面包店每天生产个面包,第天生产的第块面包的价格为,同时,一天购买块面包需要额外花费,现在问储备至少块面包的最低价格是多少。
数据范围:

题解:
分组背包问题。从低价到高价开始选择面包,本题关键是考虑额外的部分。
考虑第天的第块面包,需要多加,对于第块面包,需要多加,所以对于第块面包多的价值就是。所以预处理下第天的前缀和即可。同时要考虑到每天得有面包吃,所以转移时前一个状态必须从开始。
时间复杂度:

代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
template<typename T>
inline T Read() {
    T x = 0, f = 1;
    char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    while(isdigit(ch)) {x = (x << 3) + (x << 1) + ch - '0'; ch = getchar();} 
    return x * f;
}

#define read() Read<int>()
#define readl() Read<long long>()

const int N = 310;
int f[N][N];
int c[N][N];

int main()
{
    int n = read(), m = read();
    for(int i = 1; i <= n; i++) { 
        for(int j = 1; j <= m; j++) c[i][j] = read();
        sort(c[i] + 1, c[i] + 1 + m);
        c[i][0] = 0;
        for(int j = 1; j <= m; j++) c[i][j] += c[i][j - 1] + (2 * j - 1);
    }

    memset(f, 0x3f, sizeof f);
    f[0][0] = 0;

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            for(int k = max(i - 1, j - m); k <= j; k++)
                f[i][j] = min(f[i][j], f[i - 1][k] + c[i][j - k]);

    printf("%d\n", f[n][n]);
    return 0; 
}