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水题,然而不想上传,太水了。

posted @ 2016-05-25 18:59  Helica  阅读(173)  评论(0编辑  收藏  举报