POJ - 1661 Help Jimmy (Dijkstra+堆优化)

POJ - 1661 Help Jimmy (Dijkstra+堆优化)

我的博客

题目链接

题意

​ 一个人从高处落下,落下时可能落至地面或者板子,当他落至地面时结束。我简化下题意就是要求,他在板子上移动的距离再加上开始落下时的高度即可。

​ 题目保证有解,不会出现落下时的高度超出限制高度的情况。
这道题主要难在建图,算法就是dijkstra+堆优化的板子。

思路

​ 每个板子的左右端点当作路径中的点用dist数组存下,然后把起点当作点存入。把能够直接到地面的点存入并记录权值为零。

AC代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;

const int BMAX = 1005;
const int DMAX = 2005;
struct plant {
    int x1, x2, h;
    plant() : x1(-1),x2(-1),h(-1) {}
    bool operator < (const plant a) const {
        if(h != a.h) return h > a.h;
        else if(x1 != a.x1) return x1 < a.x1;
        else return x2 < a.x2;
    }
} pp[BMAX];
const int INF = 0x3f3f3f3f;
struct qnode {
    int v, c;
    qnode(int _v = 0, int _c = 0) : v(_v), c(_c) {}
    bool operator < (const qnode &r) const {
        return c > r.c;
    }
};
struct Edge {
    int v, cost;
    Edge(int _v = 0, int _cost = 0) : v(_v), cost(_cost) {}
};
vector<Edge> E[DMAX];
bool vis[DMAX];
int dist[DMAX];
void Dijkstra(int n, int start) {
    memset(vis, false, sizeof(vis));
    for(int i = 1; i <= n; i++) {
        dist[i] = INF;
        vis[i] = false;
    }
    priority_queue<qnode> que;
    while(!que.empty()) que.pop();
    dist[start] = 0;
    que.push(qnode(start, 0));
    qnode tmp;
    while(!que.empty()) {
        tmp = que.top();
        que.pop();
        int u = tmp.v;
        if(vis[u]) continue;
        vis[u] = true;
        for(int i = 0; i < E[u].size(); i++) {
            int v = E[tmp.v][i].v;
            int cost = E[u][i].cost;
            if(!vis[v] && dist[v] > dist[u] + cost) {
                dist[v] = dist[u] + cost;
                que.push(qnode(v, dist[v]));
            }
        }
    }
}
void addedge(int u, int v, int w) {
    E[u].push_back(Edge(v, w));
}
void init() {
    for(int i = 0; i < DMAX; i++) {
        E[i].clear();
    }
    memset(pp, 0, sizeof(pp));
}
int main() {
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    int T;
    scanf("%d", &T);
    while(T--) {
        init();
        int tot = 1;
        int n, x, y, MAX;
        scanf("%d%d%d%d", &n, &x, &y, &MAX);
        pp[0].x1 = pp[0].x2 = x, pp[0].h = y;
        for(int i = 1; i <= n; i++) {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            if(pp[0].h >= c) {
                pp[tot].x1 = a, pp[tot].x2 = b, pp[tot].h = c;
                tot++;
            }
        }
//        printf("%d\n", tot);
        sort(pp+1, pp + tot);
        for(int i = 0; i <= tot; i++) {
            bool l, r;
            l = r = false;
            for(int j = i+1; j <= tot && pp[i].h - pp[j].h <= MAX; j++) {
                if(!l && pp[i].x1 >= pp[j].x1 && pp[i].x1 <= pp[j].x2) {
                    int tt1 = pp[i].x1-pp[j].x1;
                    int tt2 = pp[j].x2-pp[i].x1;
                    addedge(i << 1, j << 1, pp[i].x1-pp[j].x1);
                    addedge(i << 1, j << 1 ^ 1, pp[j].x2-pp[i].x1);
                    l = true;
                }
                if(!r && pp[i].x2 >= pp[j].x1 && pp[i].x2 <= pp[j].x2) {
                    int tt1 = pp[i].x2-pp[j].x1;
                    int tt2 = pp[j].x2-pp[i].x2;
                    addedge(i << 1 ^ 1, j << 1, pp[i].x2-pp[j].x1);
                    addedge(i << 1 ^ 1, j << 1 ^ 1, pp[j].x2-pp[i].x2);
                    r = true;
                }
            }
            if(!l && pp[i].h <= MAX) addedge(i << 1, (tot+1)<<1, 0);
            if(!r && pp[i].h <= MAX) addedge(i << 1 ^ 1, (tot+1)<<1, 0);
        } //共有(tot+1)*2个点,起点为1
        Dijkstra((tot+1)<<1, 1);
        printf("%d\n", dist[(tot+1)<<1]+y);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值