您的位置:首页 > 其它

HDU 3480 Division(斜率优化DP)

2012-08-27 00:46 387 查看

Division

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 999999/400000 K (Java/Others)
Total Submission(s): 1672 Accepted Submission(s): 630


[align=left]Problem Description[/align]
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.

[align=left]Input[/align]
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.

[align=left]Output[/align]
For each test case, output one line containing exactly one integer, the minimal total cost. Take a look at the sample output for format.

[align=left]Sample Input[/align]

2 3 2 1 2 4 4 2 4 7 10 1

[align=left]Sample Output[/align]

Case 1: 1 Case 2: 18

Hint
The answer will fit into a 32-bit signed integer.

[align=left]Source[/align]
2010 ACM-ICPC Multi-University Training Contest(5)——Host by BJTU

[align=left]Recommend[/align]
zhengfeng

首先从小到大排序。

然后设 dp[i][j]表示前j个数分成i组的最小花费。

则 dp[i][j]=min{dp[i-1][k]+(a[j]-a[k+1])^2} 0<k<j;

利用斜率优化DP,整理下就可以出来了。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int MAXN=10010;
const int MAXM=5010;
int a[MAXN];
int dp[MAXM][MAXN];
int n,m;
int q[MAXN];
int head,tail;
int DP()
{
for(int i=1;i<=n;i++)
dp[1][i]=(a[i]-a[1])*(a[i]-a[1]);
for(int i=2;i<=m;i++)
{
head=tail=0;
q[tail++]=i-1;
for(int j=i;j<=n;j++)
{
while(head+1<tail)
{
int p1=q[head];
int p2=q[head+1];
int x1=a[p1+1];
int x2=a[p2+1];
int y1=dp[i-1][p1]+x1*x1;
int y2=dp[i-1][p2]+x2*x2;
if((y2-y1)<=2*a[j]*(x2-x1))head++;
else break;
}
int k=q[head];
dp[i][j]=dp[i-1][k]+(a[j]-a[k+1])*(a[j]-a[k+1]);
while(head+1<tail)
{
int p1=q[tail-2];
int p2=q[tail-1];
int p3=j;
int x1=a[p1+1];
int x2=a[p2+1];
int x3=a[p3+1];
int y1=dp[i-1][p1]+x1*x1;
int y2=dp[i-1][p2]+x2*x2;
int y3=dp[i-1][j]+x3*x3;
if((y3-y2)*(x2-x1)<=(y2-y1)*(x3-x2))tail--;
else break;
}
q[tail++]=j;
}
}
return dp[m]
;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int T;
scanf("%d",&T);
int iCase=0;
while(T--)
{
iCase++;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
printf("Case %d: %d\n",iCase,DP());
}
return 0;
}


另外还有四边形不等式优化,还没有非常理解,正在学习中

/*
HDU  3840
C++ 2884ms C++

*/

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXN=10010;
const int MAXM=5010;

int a[MAXN];

int s[MAXN][MAXM];
int dp[MAXN][MAXM];
int main()
{
int n,m;
int T;
scanf("%d",&T);
int iCase=0;
while(T--)
{
iCase++;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
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 temp=dp[j][k-1]+(a[i]-a[j+1])*(a[i]-a[j+1]);
if(temp<dp[i][k])
{
dp[i][k]=temp;
s[i][k]=j;
}
}
}
}
printf("Case %d: %d\n",iCase,dp
[m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: