Division
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 999999/400000 K (Java/Others)Total Submission(s): 2142 Accepted Submission(s): 851
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
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
![](https://i-blog.csdnimg.cn/blog_migrate/3dd1058b5d51c7f6e78982cdf3fbbd51.jpeg)
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: 18HintThe answer will fit into a 32-bit signed integer.从明显可以得到递推公式dp[i][j]=min(dp[k][j-1]+cos(k+1,i)),dp[i][j]表示第i个数,有j个分组所得的最小和!然后就可以斜率优化了,当然,主要还是要注意状态的转移,倒着写!#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define MAXN 10005 int prime[MAXN],cut[5050],dp[MAXN][5050],queue[MAXN],s,e; double ff(int a,int b,int i,int j) { return (((dp[a][j-1]-dp[b][j-1]+prime[a+1]*prime[a+1]-prime[b+1]*prime[b+1])/2.0/(prime[a+1]-prime[b+1]))); } bool afterm(int a,int b,int c,int i,int j) { if(ff(b,c,i,j)<ff(a,b,i,j)) return true; return false; } int fmin(int a,int b) { if(a<b) return a; return b; } bool cmp(int a,int b) { return a<b; } int getint() { int sum; char c; while(c=getchar()) { if(c>='0'&&c<='9') { sum=c-'0'; break; } } while(c=getchar()) { if(c<'0'||c>'9') { break; } sum=sum*10+c-'0'; } return sum; } int main() { int tcase,T,i,n,m,j,k,temp,cnt; tcase=1; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { prime[i]=getint(); } if (m >= n) { printf("0\n"); continue; } sort(prime+1,prime+n+1,cmp); cnt; for (cnt = 0, i = 1; i <= n; i++) if (i == 1 || prime[i] != prime[i - 1]) prime[++cnt] = prime[i]; n = cnt; s=e=0; for(i=1;i<=n;i++) { dp[i][1]=(prime[i]-prime[1])*(prime[i]-prime[1]); } for(j=2;j<=m;j++) { { s=e=0; queue[e++]=j-1; for(i=j;i<=n;i++) { //temp=queeu; while(s<e-1&&(ff(queue[s],queue[s+1],i,j)<=prime[i]))//¶ÓÍ·×îÓÅ { s++; } k=queue[s]; dp[i][j]=dp[k][j-1]+(prime[i]-prime[k+1])*(prime[i]-prime[k+1]); temp=i; while(s<e-1&&afterm(queue[e-2],queue[e-1],temp,i,j)) { e--; } queue[e++]=temp; } } } printf("Case %d: %d\n",tcase++,dp[n][m]); } return 0; }