Training Plan
小Q同学为了准备今年的ICPC Regional,计划在天之内刷掉道题,每道题有一个难度值,其中第道题的难度值为。
然而处于半颓废状态中的小Q同学不希望在同一天中做难度差距悬殊的题目,定义第天中刷的题的难度的最大值减最小值为(如果第天没有刷题,则),那么整个计划的难度为。
小Q同学可以按照任意的顺序刷题,并且一天中可以刷任意多道题,但是每道题只需要做一次,现在小Q同学想知道完成这个计划的总难度的最小值是多少。
Input
第一行是一个正整数,表示测试数据的组数,
对于每组测试数据,
第一行是两个整数和,表示题数和天数,
第二行是个整数,表示每道题的难度值。
Output
对于每组测试数据,输出一个整数,表示整个计划的最小难度。
Sample Input
2 3 3 1 2 3 3 2 1 2 3
Sample Output
0 1
Hint
对于第一组样例,最优方案是一天刷一题。
对于第二组样例,一个最优方案是第一天刷难度值为1和2的题,第二天刷难度值为3的题。
Source
题解:
我们从小到大选择 就是将其分为m份
设定dp[i][j] 为前i天刷了j题的最小答案
转移为:
dp[i][j] = min{dp[i-1][j](选择这天不刷题), dp[i-1][k] + (a[j]- [k+1]) 1<=k<=j }
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include<map> #include<queue> using namespace std; const int N = 1e3+10, M = 30005, mod = 1e9 + 7, inf = 1e9+1000; typedef long long ll; ll dp[N][N]; int n,m,a[N]; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); for(int i=1;i<=n;i++) dp[0][i] = 1e18; dp[0][0] = 0; for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { dp[i][j] = dp[i-1][j]; for(int k=1;k<=j;k++) { dp[i][j] = min(dp[i][j], dp[i-1][k-1] + abs(a[j]-a[k])*1ll*abs(a[j]-a[k])); } } } cout<<dp[m][n]<<endl; } return 0; }