poj1661Help Jimmy

从下向上倒推,dp[i][0]表示从第j块板子到第i块板子的左边的最小路程,dp[i][1]表示从第j块板子到第i块板子的右边的最小路程,
先从小到大给板子排序,如果当前第i块板子下面有第j块板子的话,则比较从当前 第j块板子的左右分别到第i块板子的左右最小路程
有点细节要注意 ,首先要倒推到起始点,就是人落下的点,所以要多记录一个"人"板子,然后应该初始化DP为一个较大值,因为你第j块板子如果有一端不能达到i则就要给他一个极大值

#include <iostream>
#include <algorithm>
using namespace std;
struct Ban
{
       int x, y, h;      
}ban[1100];
int dp[1100][2];
bool cmp(Ban a, Ban b)
{
     return a.h < b.h;    
}
int main()
{
    //freopen("IN.txt", "r", stdin);
//freopen("OUT.txt", "w", stdout);
    int t;
    scanf("%d", &t);
    while (t --){
          int n, sx, sy, h;
          scanf("%d%d%d%d", &n, &sx, &sy, &h);
          for (int i = 1; i <= n; i ++){
              scanf("%d%d%d", &ban[i].x, &ban[i].y, &ban[i].h); 
          } 
          ban[n+1].x = sx, ban[n+1].y = sx, ban[n+1].h = sy;
          sort(ban+1, ban+1+n, cmp);
          //memset(dp, , sizeof(dp));
          bool check1, check2;
          dp[0][0] = dp[0][1] = 0;
          for (int i = 1; i <= n+1; i ++){
              check1 = check2 = false;
              dp[i][0] = dp[i][1] = 0xffffff;
              for (int j = i-1; j >= 0; j --){
                  if (ban[i].h - ban[j].h > h || (check1 && check2))break;
                  if (!check1){
                     if (!j)dp[i][0] = 0;
                     else
                     if (ban[j].y >= ban[i].x && ban[i].x >= ban[j].x){
                        dp[i][0] = min(dp[j][1]+(ban[j].y - ban[i].x), dp[j][0]+(ban[i].x-ban[j].x));
                        check1 = true;            
                     }           
                  }
                  if (!check2){
                     if (!j)dp[i][1] = 0;
                     else
                     if (ban[j].x <= ban[i].y && ban[j].y >= ban[i].y){
                        dp[i][1] = min(dp[j][0]+(ban[i].y-ban[j].x), dp[j][1]+(ban[j].y-ban[i].y));        
                        check2 = true;     
                     }            
                  }
              }   
          }
          //
          printf("%d\n", dp[n+1][0]+sy);
    }
    return 0;   
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值