思路:
首先我们每天肯定都是按照价格从低到高买糖果,所以决策只需要关注当前天买了多少个。
f[i][j]代表前i天已经买了j颗糖果的最小花费,枚举第i天买了多少糖果。
f[i][j] = min(f[i-1][k] + sum[i][i-k] + (j-k)*(j-k)); (k从i-m到i-1枚举)
普通的背包问题,注意边界。。。。。。。。。。。。
用到前缀和
#include<iostream>
#include<string>
#include<math.h>
#include<algorithm>
#include<vector>
//#include<bits/stdc++.h>
const int inf = 0x3f3f3f3f;
const int INF = 0x3f3f3f3f;
typedef long long ll;
ll gcd(ll a, ll b)
{
	return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
	return a * b / (gcd(a, b));
}
#define PII pair<int,int>
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 7;
int qmi(int a, int k, int p)		//快速幂模板
{
	int res = 1;
	while (k)
	{
		if (k & 1) res = (ll)res * a % p;
		k >>= 1;
		a = (ll)a * a % p;
	}
	return res;
}
///////////////////////////////////////////////////////////
int dp[1005][1005];
int s[1005][1005];
int main() {
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
			cin >> s[i][j];
		sort(s[i] + 1, s[i] + 1 + m);
		for (int j = 1; j <= m; j++)
			s[i][j] += s[i][j - 1];
	}
	memset(dp, inf, sizeof(dp));
	dp[0][0] = 0;
	for(int i=1;i<=n;i++)
		for(int j=i;j<=min(i*m,n);j++)
			for (int k = i - 1; k <= j; k++) {
				dp[i][j] = min(dp[i][j], dp[i - 1][k] + s[i][j - k] + (j - k) * (j - k));
			}
	cout << dp[n][n] << endl;
	return 0;
}