UVa 12170 Easy Climb
题目:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=24844
思路:
引别人一个题解琢磨一下:
from:http://blog.csdn.net/glqac/article/details/45257659
代码:
1 #include<iostream> 2 #include<algorithm> 4 #define FOR(a,b,c) for(int a=(b);a<(c);a++) 5 using namespace std; 6 7 typedef long long LL; 8 9 const int maxn = 100 + 5; 10 const int maxx = maxn*maxn*2; 11 const LL INF = (1LL << 60); 12 13 LL h[maxn],x[maxx],dp[2][maxx]; 14 15 int main() { 16 int T; cin>>T; 17 while(T--) { 18 int n; LL d; 19 cin>>n>>d; 20 FOR(i,0,n) cin>>h[i]; 21 if(abs(h[0]-h[n-1])> (n-1)*d) { //input无解 22 cout<<"impossible "; 23 continue; 24 } 25 26 int nx=0; 27 FOR(i,0,n) 28 FOR(j,-(n-1),n) //-(n-1)..(n-1) 29 x[nx++]=h[i]+j*d; 30 sort(x,x+nx); //从小到大单调增长 31 nx=unique(x,x+nx)-x; //去重且返回最终尾标 //x构造为修改后的所有可能取值 32 33 FOR(i,0,nx) { //dp_init 34 dp[0][i]=INF; 35 if(x[i]==h[0]) dp[0][i]=0; //原本第i个就是h[0] //第0个数不能修改 36 } 37 38 //d[i][j]意味着已经修改i个数其中第i个数修改成为x[j]需要的最小费用 39 40 int t=0; //滚动数组的空间优化 41 FOR(i,1,n) { 42 int k=0; 43 FOR(j,0,nx) { 44 while(k<nx && x[k]<x[j]-d) k++; //两者的取值必须不超过d 45 while(k+1<nx && x[k+1]<=x[j]+d && dp[t][k+1]<=dp[t][k]) //在 滑动窗口 中最小的 46 k++; 47 //刷表法 更新 48 if(dp[t][k]==INF) dp[t^1][j]=INF; 49 else dp[t^1][j]=dp[t][k]+abs(x[j]-h[i]); 50 } 51 t^=1; 52 } 53 54 FOR(i,0,nx) if(x[i]==h[n-1]) //第N-1个数不能修改 55 cout<<dp[t][i]<<" "; 56 57 } 58 return 0; 59 }