UESTC_最少花费 2015 UESTC Training for Dynamic Programming

时间:2023-03-09 17:19:13
UESTC_最少花费 2015 UESTC Training for Dynamic Programming<Problem D>

D - 最少花费

Time Limit: 30000/10000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit Status

Bob是一个魔法师。这天,他被N座山所阻挡,这些山排成一排,每座山有一个高度。Bob需要从左往右每次跳到相邻的一座山上,相邻的两座山的高度差不能超过K,当从高度差为D的一座山跳到另一座山时要花A×D的魔法值。Bob可以改变一座山的高度,但调整后的高度不能小于0或大于1000,改变S的高度需要花费S×S的魔法值。现在已知每座山的高度,求Bob跳完所有山后魔法值的最少花费。

Input

第一行一个整数T(T≤150),表示数据组数。

每组第一行有3个整数N(1≤N≤1000), K(0≤K≤1000), A(0≤A≤1000)。

接下来N个整数,按从左往右的顺序表示山的高度,山的高度在0到1000之间。

Output

对于每组数据,输出一个整数,表示最少花费。

Sample input and output

Sample Input Sample Output
2
1 1 1
1
3 1 10
1 2 3
0
2

解题报告:

我们令f( i , j ) 将第 i 座山高度改为 j 的最小花费.

F( i , j ) = min ( f( i – 1 , k ) + abs ( j – k ) + (i – h[i]) ^ 2)

不妨有 j > k

F( i , j ) = min ( f( i – 1 , k ) – k ) + j + (i – h[i]) ^ 2

即维护一个单调队列来更新 j > k的情况.

J < k 的情况同理.

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
typedef long long ll;
using namespace std;
const int maxn = 1e3 + ;
int a,n,dl,q[maxn];
ll f[maxn][maxn],h[maxn]; int main(int argc,char *argv[])
{
int Case;
scanf("%d",&Case);
while(Case--)
{
scanf("%d%d%d",&n,&dl,&a); //DL = deeplimit
for(int i = ; i <= n ; ++ i)
scanf("%lld",&h[i]);
for(int i = ; i <= n ; ++ i)
for(int j = ; j <= ; ++ j)
f[i][j] = ;
for(int i = ; i <= ; ++ i)
f[][i] = (i-h[])*(i-h[]);
for(int i = ; i <= n ; ++ i)
{
int front = , rear = ;
for(int j = ; j <= ; ++ j)
{
while(rear > front && f[i-][q[rear-]] - a*q[rear-] >= f[i-][j] - a*j)
rear--;
q[rear++] = j;
while(rear - front > && j > q[front] + dl)
front++;
f[i][j] = min(f[i][j],(j-h[i])*(j-h[i]) + f[i-][q[front]] + (j - q[front]) * a);
}
front = rear = ;
for(int j = ; j >= ; -- j)
{
while(rear > front && f[i-][q[rear-]] + q[rear-]*a >= f[i-][j] + j*a)
rear--;
q[rear++] = j;
while(rear - front > && q[front] > j + dl)
front++;
f[i][j] = min(f[i][j],(j-h[i])*(j-h[i]) + f[i-][q[front]] + (q[front] - j) * a );
}
}
ll ans = ;
for(int i = ; i <= ; ++ i)
ans = min(ans,f[n][i]);
printf("%lld\n",ans);
}
return ;
}