[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 }

 

posted @ 2017-04-21 15:52  Kirai  阅读(238)  评论(0编辑  收藏  举报