比赛 20120614 评测结果 AAWWAWAAWA
题目名称 工作指派 最终得分 60
用户昵称 ZhouHang 运行时间 0.000 s
代码语言 C++ 内存使用 0.00 MiB
提交时间 2012-06-14 16:31:12
显示代码纯文本
/**
*Prob	: dividea
*Data	: 2012-6-14
*Sol	: 动归+决策单调性
*Author : Zhou Hang
*/

#include <cstdio>
#include <cstring>
#include <algorithm>

#define lld long long
#define MaxN 100100

using namespace std;

int n,k,c;
lld f[MaxN],a[MaxN];

lld min(lld x,lld y)
{
	if (x<y) return x;
	return y;
}

lld Sqr(int x)
{
	return (lld)x*x;
}

lld cal(int x,int y)
{
	return f[x]+c+Sqr(a[y]-a[x+1]);
}

//朴素
int dp1()
{
	memset(f,127,sizeof(f));
	f[0]=0;
	
	for (int i=1; i<k; i++)
		f[i]=cal(0,i);
	
	for (int i=k; i<=n; i++)
	 for (int j=0; j<=i-k; j++)
		f[i]=min(f[i],cal(j,i));

	printf("%I64d\n",f[n]);
}

//决策单调性
int dp2()
{
	memset(f,127,sizeof(f));
	f[0]=0;
	
	for (int i=1; i<k; i++)
		f[i]=cal(0,i);

	int head=0,tmp;
	for(int i=k; i<=n; i++)
	{
		tmp=head;
		for(int j=tmp; j<=i-k; j++)
		 if( f[i]>=cal(j,i) )
		 {
			f[i]=cal(j,i);
			tmp=j;                                                                         
		 }
		head=tmp;
	}
	
	printf("%I64d\n",f[n]);
}

int main()
{
	freopen("dividea.in","r",stdin);
	freopen("dividea.out","w",stdout);
	
	scanf("%d%d%d",&n,&k,&c);
	for (int i=1; i<=n; i++)
		scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	
	if (n<=9000) dp1();
	else dp2();

	fclose(stdin); fclose(stdout);
	return 0;
}