题意:
共
n
天
,
每
天
有
m
种
糖
果
可
以
买
,
也
可
以
不
买
共n天,每天有m种糖果可以买, 也可以不买
共n天,每天有m种糖果可以买,也可以不买
价
钱
是
c
i
j
价钱是c_{ij}
价钱是cij
每
天
买
k
个
糖
果
需
要
额
外
支
付
k
2
的
钱
每天买k个糖果需要额外支付k^2的钱
每天买k个糖果需要额外支付k2的钱
要
每
天
都
能
有
一
个
糖
果
吃
要每天都能有一个糖果吃
要每天都能有一个糖果吃
问
最
少
花
多
少
钱
每
天
都
能
有
糖
果
吃
问最少花多少钱每天都能有糖果吃
问最少花多少钱每天都能有糖果吃
题解:
n
,
m
<
=
300
n,m<=300
n,m<=300
最
优
解
,
并
且
没
有
策
略
进
行
贪
心
最优解,并且没有策略进行贪心
最优解,并且没有策略进行贪心
那
么
考
虑
d
p
那么考虑dp
那么考虑dp
d
p
[
i
]
[
j
]
第
i
天
已
经
有
j
个
糖
果
的
最
小
花
费
dp[i][j]第i天已经有j个糖果的最小花费
dp[i][j]第i天已经有j个糖果的最小花费
对
于
每
一
天
肯
定
优
先
买
最
便
宜
的
几
个
糖
果
对于每一天肯定优先买最便宜的几个糖果
对于每一天肯定优先买最便宜的几个糖果
那
么
对
这
一
天
的
糖
果
排
序
,
并
且
求
出
前
缀
和
那么对这一天的糖果排序,并且求出前缀和
那么对这一天的糖果排序,并且求出前缀和
然
后
开
始
枚
举
每
一
天
枚
举
总
共
买
糖
果
的
数
量
和
当
天
购
买
糖
果
的
数
量
然后开始枚举每一天枚举总共买糖果的数量和当天购买糖果的数量
然后开始枚举每一天枚举总共买糖果的数量和当天购买糖果的数量
进
行
转
移
即
可
进行转移即可
进行转移即可
最
后
d
p
[
n
]
[
n
]
为
最
终
答
案
最后dp[n][n]为最终答案
最后dp[n][n]为最终答案
AC代码
/*
Author : zzugzx
Lang : C++
Blog : blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
//const int mod = 998244353;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int maxn = 1e6 + 10;
const int N = 3e2 + 5;
const ll inf = 0x3f3f3f3f;
const int dir[][2]={{0, 1}, {1, 0}, {0, -1}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
int a[N][N], dp[N][N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
for (int i = 1; i <= n; i++)
sort(a[i] + 1, a[i] + 1 + m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] += a[i][j - 1];
mem(dp, inf);
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, min(j, (i - 1) * m)); k++)
dp[i][j] = min(dp[i][j], dp[i - 1][k] + a[i][j - k] + (j - k) *(j - k));
cout << dp[n][n];
return 0;
}