POJ 1661 Help Jimmy (DP)

来源:互联网 发布:ubuntu c 开发环境 编辑:程序博客网 时间:2024/06/01 08:58
"Help Jimmy" 是在下图所示的场景上完成的游戏。

场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。

Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。

设计一个程序,计算Jimmy到底地面时可能的最早时间。

Input

第一行是测试数据的组数t(0 <= t <= 20)。每组测试数据的第一行是四个整数N,X,Y,MAX,用空格分隔。N是平台的数目(不包括地面),X和Y是Jimmy开始下落的位置的横竖坐标,MAX是一次下落的最大高度。接下来的N行每行描述一个平台,包括三个整数,X1[i],X2[i]和H[i]。H[i]表示平台的高度,X1[i]和X2[i]表示平台左右端点的横坐标。1 <= N <= 1000,-20000 <= X, X1[i], X2[i] <= 20000,0 < H[i] < Y <= 20000(i = 1..N)。所有坐标的单位都是米。

Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。

Output

对输入的每组测试数据,输出一个整数,Jimmy到底地面时可能的最早时间。




题意是中文简单易懂。
对于每一块板子,到达板子时,要么向左,要么向右,那么就正向推可以设一个dp,dp[i][0]/dp[i][1]。
dp[i][0],表示到达第 i 块板子左端点的最短时间。
dp[i][1],表示到达第 i 块板子右端点的最短时间。
先对高度排序,让板子从高到低排序。
对于当前 i 板子,只能由从 1 到 i-1 转移来,那么就暴力枚举前 i-1 块板子,然后再根据规则推就行了。
但是因为上面的板子挡住了现在的板子,那么就可能到达不了这块板子,所有这里要判断,是否能从第 j 块板子到第 i 块板子。
但是怎么来判断呢:
可以将上面的板子,两个坐标看成区间,那么就把区间更新为 1 就可以了。
如果 j 块板子的端点是 1,就表示不能从这块板子到达 i 板子。
这里就要引入线段树的区间更新,模板就不说了。
但是区间的 范围是 -20000-20000
但是最多只有2000+4个点(起点+终点),那么离散化一下就可以了。
最后这段毒眼睛的代码就出来了。

其实有更简单的方法,dp[i][0]/dp[i][1],表示第 i 块板子从左/右端点到达地面的最短时间,这个也很好推的。

感觉自己弱爆了。

#include<stdio.h>#include<algorithm>#include<string>#include<string.h>#include<queue>#include<vector>#include<stack>#include<math.h>#include<map>#include<iostream>using namespace std;#define maxn 1005#define ll long longstruct nnode{    int x, y, h;} a[maxn];int n, dp[maxn][2], use[5000];vector<int> v;struct node{    int id,l,r,maxx,add;} tree[30000 * 4];int getid(int x){   return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;}void pushdown(int id){    if(tree[id].add != -1)    {        tree[id * 2].add = tree[id].add;        tree[id * 2 + 1].add = tree[id].add;        tree[id * 2].maxx = tree[id].add;        tree[id * 2 + 1].maxx = tree[id].add;        tree[id].add = -1;    }}void update(int id, int ql, int qr, int newval){    int l = tree[id].l;    int r = tree[id].r;    int mid = (l + r) / 2;    if(r < ql || qr < l)        return;    if(ql <= l && qr >= r)    {        tree[id].add = newval;        tree[id].maxx = newval;        return ;    }    pushdown(id);    if(mid >= qr)        update(id * 2, ql, qr, newval);    else if((mid + 1) <= ql)        update(id * 2 + 1, ql, qr, newval);    else    {        update(id * 2, ql, qr, newval);        update(id * 2 + 1, ql, qr, newval);    }    tree[id].maxx = max(tree[id * 2].maxx, tree[id * 2 + 1].maxx);}int querymax(int id, int ql, int qr){    int l = tree[id].l;    int r = tree[id].r;    int mid = (l + r) / 2;    if(r < ql || l > qr)        return 0;    if(ql <= l && qr >= r)        return tree[id].maxx;    pushdown(id);    if(mid >= qr)        return querymax(id * 2, ql, qr);    else if((mid + 1) <= ql)        return querymax(id * 2 + 1, ql, qr);    else        return max(querymax(id * 2, ql, qr), querymax(id * 2 + 1, ql, qr));}void build(int id, int l, int r){    tree[id].l = l;    tree[id].r = r;    tree[id].add = -1;    if(l == r)    {        tree[id].maxx = 0;        return ;    }    int mid = (l + r) / 2;    build(id * 2, l, mid);    build(id * 2 + 1, mid + 1, r);    tree[id].maxx = max(tree[id * 2].maxx, tree[id * 2 + 1].maxx);}bool cmp(nnode a, nnode b) {    return a.h > b.h;   }int main(){    int smax, t, dx, dy;    scanf("%d", &t);    while(t--)    {        memset(dp, 0x7f, sizeof(dp));        scanf("%d%d%d%d", &n, &a[0].x, &a[0].h, &smax);        a[0].y = a[0].x;                                   //加入起点        for(int i = 1; i <= n; i++)            scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].h);        n++; a[n].x = -20000;a[n].y = 20000;a[n].h = 0;    //加入终点        for(int i=0;i<=n;i++)        {            v.push_back(a[i].x);            v.push_back(a[i].y);        }        sort(v.begin(), v.end());        v.erase(unique(v.begin(), v.end()), v.end());        for(int i = 0; i <= n; i++)        {            int dx = a[i].x, dy = a[i].y;            a[i].x = getid(a[i].x);            a[i].y = getid(a[i].y);            use[a[i].x] = dx;            use[a[i].y] = dy;        }        build(1, 1, 3000);        sort(a, a + n + 1, cmp);        dp[0][0] = dp[0][1] = 0;        for(int i = 1; i <= n; i++)        {            update(1, 1, 3000, 0);            for(int j = i - 1; j >= 0; j--)            {                if(a[j].h - a[i].h > smax || a[i].x > a[j].y || a[i].y < a[j].x)                    continue;                int th = a[j].h - a[i].h;                if(a[i].x <= a[j].x && a[i].y < a[j].y) //0                {                    int maxx = querymax(1, a[j].x, a[j].x);                    if(maxx == 1)                    {                        update(1, a[j].x, a[j].y, 1);                        continue;                    }                    int l = use[a[j].x] - use[a[i].x];                    int r = use[a[i].y] - use[a[j].x];                    if(i==n) l=r=0;                    dp[i][0] = min(dp[i][0], dp[j][0] + th + l);                    dp[i][1] = min(dp[i][1], dp[j][0] + th + r);                    update(1, a[j].x, a[j].y, 1);                }                else if(a[i].x > a[j].x && a[j].y <= a[i].y) //1                {                    int maxx = querymax(1, a[j].y, a[j].y);                    if(maxx == 1)                    {                        update(1, a[j].x, a[j].y, 1);                        continue;                    }                    int l = use[a[j].y] - use[a[i].x];                    int r = use[a[i].y] - use[a[j].y];                    if(i==n) l=r=0;                    dp[i][0] = min(dp[i][0], dp[j][1] + th + l);                    dp[i][1] = min(dp[i][1], dp[j][1] + th + r);                    update(1, a[j].x, a[j].y, 1);                }                else if(a[i].x <= a[j].x && a[i].y >= a[j].y) // 0 1                {                    int maxx1 = querymax(1, a[j].x, a[j].x);                    if(maxx1 == 0)                    {                        int l = use[a[j].x] - use[a[i].x];                        int r = use[a[i].y] - use[a[j].x];                        if(i==n) l=r=0;                        dp[i][0] = min(dp[i][0], dp[j][0] + th + l);                        dp[i][1] = min(dp[i][1], dp[j][0] + th + r);                    }                    int maxx2 = querymax(1, a[j].y, a[j].y);                    if(maxx2 == 0)                    {                        int l = use[a[j].y] - use[a[i].x];                        int r = use[a[i].y] - use[a[j].y];                        if(i==n) l=r=0;                        dp[i][0] = min(dp[i][0], dp[j][1] + th + l);                        dp[i][1] = min(dp[i][1], dp[j][1] + th + r);                    }                    update(1, a[j].x, a[j].y, 1);                }            }        }        printf("%d\n", min(dp[n][0], dp[n][1]));    }    return 0;}


0 0
原创粉丝点击