题目链接:https://vjudge.net/problem/HDU-3480
Division
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 999999/400000 K (Java/Others)
Total Submission(s): 5304 Accepted Submission(s): 2093
Problem Description
Little D is really interested in the theorem of sets recently. There’s a problem that confused him a long time.
Let T be a set of integers. Let the MIN be the minimum integer in T and MAX be the maximum, then the cost of set T if defined as (MAX – MIN)^2. Now given an integer set S, we want to find out M subsets S1, S2, …, SM of S, such that
![](http://acm.hdu.edu.cn/data/images/C295-1003-1.jpg)
and the total cost of each subset is minimal.
Let T be a set of integers. Let the MIN be the minimum integer in T and MAX be the maximum, then the cost of set T if defined as (MAX – MIN)^2. Now given an integer set S, we want to find out M subsets S1, S2, …, SM of S, such that
![](http://acm.hdu.edu.cn/data/images/C295-1003-1.jpg)
and the total cost of each subset is minimal.
Input
The input contains multiple test cases.
In the first line of the input there’s an integer T which is the number of test cases. Then the description of T test cases will be given.
For any test case, the first line contains two integers N (≤ 10,000) and M (≤ 5,000). N is the number of elements in S (may be duplicated). M is the number of subsets that we want to get. In the next line, there will be N integers giving set S.
In the first line of the input there’s an integer T which is the number of test cases. Then the description of T test cases will be given.
For any test case, the first line contains two integers N (≤ 10,000) and M (≤ 5,000). N is the number of elements in S (may be duplicated). M is the number of subsets that we want to get. In the next line, there will be N integers giving set S.
Output
For each test case, output one line containing exactly one integer, the minimal total cost. Take a look at the sample output for format.
Sample Input
2
3 2
1 2 4
4 2
4 7 10 1
Sample Output
Case 1: 1
Case 2: 18
Hint
The answer will fit into a 32-bit signed integer.Source
Recommend
zhengfeng
题意:
给出一组数,把这组数分成m个集合,使得每个集合的(MAX-MIN)^2的和最小。
题解:
1.首先可以确定:每个集合的数值跨度应该尽量小,所以可以先对这些数进行排序,被分成一组的数必定是相连的。
2.设dp[i][j]为:第j个数属于第i个集合时的最小值,那么:dp[i][j] = min(dp[i-1][k] + (val[i] - val[k+1)^2),其中 i-1<=k<=j-1。
3.根据上述的状态转移方程,可算得时间复杂度为O(n^3),无法接受。因此可以用斜率优化。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int mod = 1e9+7; 17 const int MAXM = 1e5+10; 18 const int MAXN = 1e4+10; 19 20 int val[MAXN], dp[MAXN][MAXN]; 21 int q[MAXN], head, tail; 22 23 int getUP(int i, int k1, int k2) 24 { 25 return (dp[i-1][k1] + val[k1+1]*val[k1+1])- 26 (dp[i-1][k2] + val[k2+1]*val[k2+1]); 27 } 28 29 int getDOWN(int k1, int k2) 30 { 31 return 2*(val[k1+1]-val[k2+1]); 32 } 33 34 int getDP(int i, int j, int k) 35 { 36 return dp[i-1][k] + (val[j]-val[k+1])*(val[j]-val[k+1]); 37 } 38 39 int main() 40 { 41 int n, m, T; 42 scanf("%d", &T); 43 for(int kase = 1; kase<=T; kase++) 44 { 45 scanf("%d%d", &n,&m); 46 for(int i = 1; i<=n; i++) 47 scanf("%d", &val[i]); 48 49 sort(val+1, val+1+n); 50 for(int i = 1; i<=n; i++) //初始化第一段 51 dp[1][i] = (val[i]-val[1])*(val[i]-val[1]); 52 for(int i = 2; i<=m; i++) //从i-1段转移到i段 53 { 54 head = tail = 0; 55 q[tail++] = i-1; //i-1段最少要有i-1个数,故从i-1开始 56 for(int j = i; j<=n; j++) //i段最少要有i个数,故从i开始 57 { 58 while(head+1<tail && getUP(i,q[head+1],q[head])<getDOWN(q[head+1], q[head])*val[j]) head++; 59 dp[i][j] = getDP(i,j,q[head]); 60 61 while(head+1<tail && getUP(i,j,q[tail-1])*getDOWN(q[tail-1],q[tail-2])<= 62 getUP(i,q[tail-1],q[tail-2])*getDOWN(j,q[tail-1])) tail--; 63 q[tail++] = j; 64 } 65 } 66 printf("Case %d: %d ", kase, dp[m][n]); 67 } 68 }