[BNUOJ]Training Plan(贪心,dp)
题目链接:https://www.bnuoj.com/v3/problem_show.php?pid=51640
希望每天刷题难度差距不会太大,很容易知道排序后相邻两数差的绝对值最小。
题意变成了将n个数拆成m份,让这m份里相差最大的两个数的差的绝对值最小。
用dp(i,j)表示将j个数拆成i份的最优解,枚举i,j,初始化dp(i,j)为dp(i-1,j)。
再将j拆分成两部分[i,k)和[k,j],更新dp(i,j)的时候则用dp(i-1,k-1)和(a(j)-a(k))^2来更新。
dp(m, n)即为答案。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const int maxn = 550; 6 const LL inf = 1LL << 63 - 1; 7 int n, m; 8 int a[maxn]; 9 LL dp[maxn][maxn]; 10 11 int main() { 12 freopen("in", "r", stdin); 13 int T; 14 scanf("%d", &T); 15 while(T--) { 16 scanf("%d%d",&n,&m); 17 for(int i = 1; i <= n; i++) { 18 scanf("%d", &a[i]); 19 } 20 sort(a+1, a+n+1); 21 dp[0][0] = 0; 22 for(int i = 1; i <= n; i++) dp[0][i] = inf; 23 for(int i = 1; i <= m; i++) { 24 for(int j = 1; j <= n; j++) { 25 dp[i][j] = dp[i-1][j]; 26 for(int k = 1; k <= j; k++) { 27 dp[i][j] = min(dp[i][j], dp[i-1][k-1] + (LL)(a[j]-a[k])*(LL)(a[j]-a[k])); 28 } 29 } 30 } 31 cout << dp[m][n] << endl; 32 } 33 return 0; 34 }