【暑假】[深入动态规划]UVa 12170 Easy Climb

UVa 12170 Easy Climb

题目:

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=24844

思路:

 引别人一个题解琢磨一下:

【暑假】[深入动态规划]UVa 12170 Easy Climb

from:http://blog.csdn.net/glqac/article/details/45257659

代码:

 #include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<(c);a++)
using namespace std; typedef long long LL; const int maxn = + ;
const int maxx = maxn*maxn*;
const LL INF = (1LL << ); LL h[maxn],x[maxx],dp[][maxx]; int main() {
int T; cin>>T;
while(T--) {
int n; LL d;
cin>>n>>d;
FOR(i,,n) cin>>h[i];
if(abs(h[]-h[n-])> (n-)*d) { //input无解
cout<<"impossible\n";
continue;
} int nx=;
FOR(i,,n)
FOR(j,-(n-),n) //-(n-1)..(n-1)
x[nx++]=h[i]+j*d;
sort(x,x+nx); //从小到大单调增长
nx=unique(x,x+nx)-x; //去重且返回最终尾标 //x构造为修改后的所有可能取值 FOR(i,,nx) { //dp_init
dp[][i]=INF;
if(x[i]==h[]) dp[][i]=; //原本第i个就是h[0] //第0个数不能修改
} //d[i][j]意味着已经修改i个数其中第i个数修改成为x[j]需要的最小费用 int t=; //滚动数组的空间优化
FOR(i,,n) {
int k=;
FOR(j,,nx) {
while(k<nx && x[k]<x[j]-d) k++; //两者的取值必须不超过d
while(k+<nx && x[k+]<=x[j]+d && dp[t][k+]<=dp[t][k]) //在 滑动窗口 中最小的
k++;
//刷表法 更新
if(dp[t][k]==INF) dp[t^][j]=INF;
else dp[t^][j]=dp[t][k]+abs(x[j]-h[i]);
}
t^=;
} FOR(i,,nx) if(x[i]==h[n-]) //第N-1个数不能修改
cout<<dp[t][i]<<"\n"; }
return ;
}
上一篇:[Linux] PHP程序员玩转Linux系列-telnet轻松使用邮箱


下一篇:SharePoint 2010 常用技巧及方法总结