M - Help Jimmy POJ - 1661 ——dp

本文介绍了一种使用动态规划算法解决特定跳跃问题的方法。通过定义dp数组来存储到达每个木板两端点的最小成本,利用动态转移方程更新最优解。代码实现了从左端和右端跳跃的两种情况,并通过排序确保了正确性。

Think:
1知识点:dp
2动态转移方程

dp[i][0]:表示从第i个木板左端点跳跃的当前最优解
dp[i][1]:表示从第i个木板右端点跳跃的当前最优解

vjudge题目链接

以下为Accepted代码

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int inf = 0x3f3f3f3f;

struct Node{
    int x1, x2;
    int h;
    bool operator < (const Node &b) const {
        return h < b.h;
    }
}node[1014];

int H, dp[1014][2];
/*
dp[i][0]:表示从第i个木板左端点跳跃的当前最优解
dp[i][1]:表示从第i个木板右端点跳跃的当前最优解
*/

void left_time(int z, int n);
void right_time(int z, int n);
void ans_time(int n);

int main(){
    int T, i, n, x, y;
    scanf("%d", &T);
    while(T--){
        scanf("%d %d %d %d", &n, &x, &y, &H);
        node[n+1].x1 = node[n+1].x2 = x, node[n+1].h = y;
        node[0].x1 = -20000, node[0].x2 = 20000, node[0].h = 0;
        for(i = 1; i <= n; i++)
            scanf("%d %d %d", &node[i].x1, &node[i].x2, &node[i].h);
        sort(node, node+n+2);
        ans_time(n);
    }
    return 0;
}
void left_time(int z, int n){/*第z个左端点跳跃*/
    for(int i = z-1; i > 0; i--){/*注意i的范围:[1, z-1]*/
        int dh = node[z].h - node[i].h;
        if(dh <= H && node[i].x1 <= node[z].x1 && node[i].x2 >= node[z].x1){/*判断是否满足直接落在木板上的条件*/
            int u = node[z].x1 - node[i].x1;
            int v = node[i].x2 - node[z].x1;
            dp[z][0] = dh + min(dp[i][0]+u, dp[i][1]+v);
            return;/*已经直接落在木板上*/
        }
    }
    if(node[z].h <= H)/*判断是否可直接跳到地面上*/
        dp[z][0] = node[z].h;
    else
        dp[z][0] = inf;
}
void right_time(int z, int n){/*第z个右端点跳跃*/
    for(int i = z-1; i > 0; i--){/*注意i的范围:[1, z-1]*/
        int dh = node[z].h - node[i].h;
        if(dh <= H && node[i].x1 <= node[z].x2 && node[i].x2 >= node[z].x2){/*判断是否满足直接落在木板上的条件*/
            int u = node[z].x2 - node[i].x1;
            int v = node[i].x2 - node[z].x2;
            dp[z][1] = dh + min(dp[i][0]+u, dp[i][1]+v);
            return;/*已经直接落在木板上*/
        }
    }
    if(node[z].h <= H)/*判断是否可直接跳到地面上*/
        dp[z][1] = node[z].h;
    else
        dp[z][1] = inf;
}
void ans_time(int n){
    memset(dp, 0, sizeof(dp));
    for(int i = 1; i <= n+1; i++){
        left_time(i, n);/*试探左端点跳跃的最短时间*/
        right_time(i, n);/*试探右端点跳跃的最短时间*/
    }
    printf("%d\n", min(dp[n+1][0], dp[n+1][1]));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值