思路:
题目中注意的几点:
(1)The points will be in order, from smallest to largest(各点已经排序)
(2)Note that it is possible for x=y. If so, then the contractor would simply charge c.
状态转移方程:
dp[i]=min{dp[j]+(x[i]-x[j+1])^2+c}(0<j<=i-1)
(dp[i]表示前i个点的花费)
AC代码:
#include<stdio.h>
#define N 1000005
_int64 x[N];
_int64 dp[N];
int q[N];
int head,tail;
_int64 c;
int n;
_int64 getDp(int i,int j)
{
return dp[j]+c+(x[i]-x[j+1])*(x[i]-x[j+1]);
}
_int64 getUp(int j,int k)
{
return dp[j]+x[j+1]*x[j+1]-(dp[k]+x[k+1]*x[k+1]);
}
_int64 getDown(int j,int k)
{
return 2*(x[j+1]-x[k+1]);
}
int main()
{
int i;
while(scanf("%d%I64d",&n,&c)!=-1&&(n+c))
{
for(i=1;i<=n;i++)
scanf("%d",&x[i]);
dp[0]=0;
head=tail=0;
q[tail++]=0;
for(i=1;i<=n;i++)
{
while(head+1<tail&&getUp(q[head+1],q[head])<=x[i]*getDown(q[head+1],q[head]))
head++;
dp[i]=getDp(i,q[head]);
while(head+1<tail&&getUp(q[tail-1],q[tail-2])*getDown(i,q[tail-1])>=getUp(i,q[tail-1])*getDown(q[tail-1],q[tail-2]))
tail--;
q[tail++]=i;
}
printf("%I64d\n",dp[n]);
}
return 0;
}