题目描述:
小Q同学为了准备今年的ICPC Regional,计划在m天之内刷掉n道题,每道题有一个难度值,其中第i道题的难度值为a[i]。
然而处于半颓废状态中的小Q同学不希望在同一天中做难度差距悬殊的题目,定义第i天中刷的题的难度的最大值减最小值为d[i](如果第i天没有刷题,则d[i]=0),那么整个计划的难度为(每天的d[i]2 相加)。
小Q同学可以按照任意的顺序刷题,并且一天中可以刷任意多道题,但是每道题只需要做一次,现在小Q同学想知道完成这个计划的总难度的最小值是多少。
输入描述:
第一行是一个正整数T(≤ 10),表示测试数据的组数,
对于每组测试数据,
第一行是两个整数n(1≤ n ≤ 500)和m(1≤ m ≤ 500),表示题数和天数,
第二行是n个整数a[i](0≤ a[i]≤ 1000000),表示每道题的难度值。
输出描述:
对于每组测试数据,输出一个整数,表示整个计划的最小难度。
输入
2
3 3
1 2 3
3 2
1 2 3
输出
0
1
说明
对于第一组样例,最优方案是一天刷一题。
对于第二组样例,一个最优方案是第一天刷难度值为1和2的题,第二天刷难度值为3的题。
#include<bits/stdc++.h>
using namespace std;
long long a[505];
long long dp[505][505];
int main()
{
int t,n,m;
cin>>t;
while(t--)
{
cin>>n>>m;
memset(dp,0x3f3f3f3f,sizeof(dp));
for(int i=1;i<=n;i++)cin>>a[i];
dp[0][0]=0;
sort(a+1,a+1+n);
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
for(int k=j;k<=n;k++)
dp[i][k]=min(dp[i][k],dp[i-1][j-1]+(a[k]-a[j])*(a[k]-a[j]));
cout<<dp[m][n]<<endl;
}
return 0;
}
这道题一开始想了很久没想出什么好方法,最后看了一眼题解感觉也太简洁了吧!而且看了很久的题解才了解其中的意思 太难了!
分析: 1.dp[i][j] 的意思是 第i天做到第j题的最小值
2. 3个for循环分别意思 i表示第i天 j表示从第几题开始做 k表示做到第几题(j,k区间就是第i天做的题,默认j前就是前面几天做的)
3.最难理解的就是dp[i][k]=min(dp[i][k],dp[i-1][j-1]+(a[k]-a[j])*(a[k]-a[j])); 最后给出一张图作为理解 我们以dp[3][3]为例 第三天做到第三题,可以分别从1,2,3题开始做 所以就需要前一天的数据 然后分别找出最小值即可。