Division
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 999999/400000 K (Java/Others)
Total Submission(s): 4773 Accepted Submission(s): 1857
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.
题解
四边形不等式做法:
首先这个由于排序后数字递增,所以显然w[i][j] = (j - i)^2是满足区间包含单调性的。
证明满足四边形不等式也比较直观:假设四个数为
x1 = a,x2 = a + b,x3 = a + b + c,x4 = a + b + c + d
,其中b,c,d为非负数;
w[x1][x3] + w[x2][x4] = (b + c)^2 + (c + d)^2 = b^2 + 2 * c^2 + d^2 + 2 * b * c + 2 * c * d;
w[x1][x4] + w[x2][x3] = (b + c + d)^2 + c^2 = b^2 + 2 * c^2 + d^2 + 2 * b * c + 2 * c * d + 2 * b * d;
=> w[x1][x3] + w[x2][x4] <= w[x1][x4] + w[x2][x3];
于是dp[][]就满足四边形不等式,于是s[i][j] <= s[i][j + 1] <= s[i + 1][j + 1],然后转移的时候取出s[i][j - 1]到s[i + 1][j]之间的k就可以了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=10000+10;
const int M=5000+10;
int a[N],dp[N][M],s[N][M];
int n,m,Case,T;
int main()
{
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+1+n);
for (int i=1;i<=n;i++)
dp[i][1]=(a[i]-a[1])*(a[i]-a[1]),s[i][1]=1;
for (int k=2;k<=m;k++)
{
s[n+1][k]=n-1;
for (int i=n;i>=k;i--)
{
dp[i][k]=dp[k-1][k-1]+(a[i]-a[k])*(a[i]-a[k]);
s[i][k]=k;
for (int j=s[i][k-1];j<=s[i+1][k];j++)
{
int tmp=dp[j][k-1]+(a[i]-a[j+1])*(a[i]-a[j+1]);
if (tmp<dp[i][k])
{
dp[i][k]=tmp;
s[i][k]=j;
}
}
}
}
printf("Case %d: %d\n",++ Case,dp[n][m]);
}
return 0;
}