最少花费
其实这个题目跟我要长高很像的,都是需要用单调队列优化dp来解决的
只是这个题目多了一个条件山与山之间的高度差不能超过k
状态规划方程
dp[i][x]=min(dp[i-1][y]+A*abs(x-y)+(hill[i]-x)^2)
也是分高于前一座山还是低于前一座山来进行计算的
只是在队列node里面要加一个index来记录这个山是有多高的 value用来记录 单调统计量
每一次dp更新的时候 头部与尾部的index要进行比较的 如果超过k的话就head++
其余的就是普通dp的
其实这个题目跟我要长高很像的,都是需要用单调队列优化dp来解决的
只是这个题目多了一个条件山与山之间的高度差不能超过k
状态规划方程
dp[i][x]=min(dp[i-1][y]+A*abs(x-y)+(hill[i]-x)^2)
也是分高于前一座山还是低于前一座山来进行计算的
只是在队列node里面要加一个index来记录这个山是有多高的 value用来记录 单调统计量
每一次dp更新的时候 头部与尾部的index要进行比较的 如果超过k的话就head++
其余的就是普通dp的
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 0x3fffffff
using namespace std;
int T,N,K,A,i,j,maxh;
int head,tail,temp;
int dp[1005][1005];
int hill[1005];
struct node
{
int index;
int val;
}que[1005];
int main()
{
//freopen("1.txt","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&N,&K,&A);
maxh = 0;
for(i=0;i<N;i++)
{
scanf("%d",&hill[i]);
maxh = max(maxh,hill[i]);
}
if(N==1)
{
printf("0\n");
continue;
}
for(i=0;i<N;i++)
memset(dp[i],inf,sizeof(dp[i]));
for(i=0;i<=maxh;i++)
dp[0][i]=(i-hill[0])*(i-hill[0]);
for(i=1;i<N;i++)
{
//当比前一座山高时 x<= y <=min(x+k,maxh)
head = tail = 0;
for(j=0;j<=maxh;j++)
{
temp = dp[i-1][j]-A*j;
while(head<tail&&que[tail-1].val>temp)
tail--;
que[tail].val = temp;
que[tail++].index = j;
if(que[tail-1].index-que[head].index<=K)
dp[i][j] = que[head].val+A*j+(j-hill[i])*(j-hill[i]);
else
{
head++;
dp[i][j] = que[head].val+A*j+(j-hill[i])*(j-hill[i]);
}
}
//当比前一座上矮时 max(0,x-k)<= y <=x
head = tail = 0;
for(j=maxh;j>=0;j--)
{
temp = dp[i-1][j] + A*j;
while(head<tail&&que[tail-1].val>temp)
tail--;
que[tail].val = temp;
que[tail++].index=j;
if(que[head].index-que[tail-1].index<=K)
{
dp[i][j]=min(dp[i][j],que[head].val-A*j+(j-hill[i])*(j-hill[i]));
}
else
{
head++;
dp[i][j]=min(dp[i][j],que[head].val-A*j+(j-hill[i])*(j-hill[i]));
}
}
}
int ans = inf;
for(i=0;i<=maxh;i++)
{
ans = min(ans,dp[N-1][i]);
}
printf("%d\n",ans);
}
return 0;
}