POJ 1661-Help Jimmy-dp
一道dp模拟题。
给n个板子和一个初始坐标xy,从x,y开始向下跳,有一个最高的下跳距离。
在板子上走和下跳都消耗时间。计算到达地面的最短时间。
把板子按高度排序
dp[i][0]表示到达第i块板子左边沿的时间,dp[i][1]表示到达右边沿的时间。
则 dp[i][0] = min(dp[k][0]+f(),dp[k][1]+f() ) k为小于i的可以跳到i上的板子。f()表示从k的左/右边沿到i的左边沿需要的时间。
dp[i][1] = min(dp[k][0]+f(),dp[k][1]+f())
注意判断k是否能跳到i上比较麻烦,k这一端的坐标在i内,且k还没有往下跳的板子,因为一块板子的一端只可能跳到唯一的一块板子,或者地面。
最后维护可以直接跳到地面的板子一端的dp值的最小值。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 const int maxn = 1000+10; 8 const int INF = 0x3f3f3f3f; 9 10 struct Table{ 11 int l,r; 12 int height; 13 bool operator < (const Table &rhs) const 14 { 15 return height > rhs.height; 16 } 17 }table[maxn]; 18 19 int N,X0,Y0,Max; 20 int T; 21 int dp[maxn][2]; 22 int vis[maxn],next[maxn][2]; 23 24 bool check(int i,int j) 25 { 26 if(table[j].height - table[i].height <= Max && table[j].height != table[i].height) 27 return true; 28 else 29 return false; 30 } 31 32 int main() 33 { 34 scanf("%d",&T); 35 while(T--) 36 { 37 scanf("%d%d%d%d",&N,&X0,&Y0,&Max); 38 for(int i=1;i<=N;i++) 39 { 40 scanf("%d%d%d",&table[i].l,&table[i].r,&table[i].height); 41 if(table[i].l > table[i].r) 42 swap(table[i].l,table[i].r); 43 } 44 45 sort(table+1,table+1+N); 46 memset(vis,0,sizeof vis); 47 memset(next,0,sizeof next); 48 49 for(int i=0;i<=N;i++) 50 dp[i][0] = dp[i][1] = INF; 51 int ans = INF; 52 int flag = 0; 53 54 for(int i=1;i<=N;i++) 55 { 56 if(Y0 - table[i].height > Max) break; 57 if(X0 >= table[i].l && X0 <= table[i].r) 58 { 59 dp[i][0] = Y0 - table[i].height + X0 - table[i].l; 60 dp[i][1] = Y0 - table[i].height + table[i].r - X0; 61 vis[i] = true; 62 flag = 1; 63 break; 64 } 65 } 66 67 if(!flag) 68 { 69 printf("%d\n",Y0); 70 continue; 71 } 72 73 for(int i=1;i<=N;i++) 74 { 75 for(int j=i-1;j>=1;j--) if(check(i,j) && vis[j]) 76 { 77 if(!next[j][0] && table[j].l <= table[i].r && table[j].l >= table[i].l) 78 { 79 next[j][0] = true; 80 vis[i] = true; 81 dp[i][0] = min(dp[j][0]+table[j].height-table[i].height+table[j].l-table[i].l,dp[i][0]); 82 dp[i][1] = min(dp[j][0]+table[j].height-table[i].height+table[i].r-table[j].l,dp[i][1]); 83 } 84 if(!next[j][1] && table[j].r >= table[i].l && table[j].r <= table[i].r ) 85 { 86 next[j][1] = true; 87 vis[i] = true; 88 dp[i][0] = min(dp[j][1]+table[j].height-table[i].height+table[j].r-table[i].l,dp[i][0]); 89 dp[i][1] = min(dp[j][1]+table[j].height-table[i].height+table[i].r-table[j].r,dp[i][1]); 90 } 91 } 92 //printf("l:%d r:%d \n",dp[i][0],dp[i][1]); 93 } 94 95 for(int i=N;i>=1;i--) if(vis[i] && table[i].height <= Max) 96 { 97 if(!next[i][0]) ans = min(ans,dp[i][0]+table[i].height); 98 if(!next[i][1]) ans = min(ans,dp[i][1]+table[i].height); 99 100 //printf("h:%d l:%d r:%d [%d,%d] \n",table[i].height,dp[i][0],dp[i][1],next[i][0],next[i][1]); 101 } 102 printf("%d\n",ans); 103 } 104 }
最近做了好多dp水题,然而不想上传,太水了。