POJ 1661 Help Jimmy (DP)
2017-04-19 20:39
459 查看
"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 块板子从左/右端点到达地面的最短时间,这个也很好推的。
感觉自己弱爆了。
场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。
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 long struct 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 .x = -20000;a .y = 20000;a .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) { 4000 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 [0], dp [1])); } return 0; }
相关文章推荐
- POJ - 1661 Help Jimmy(DP)
- poj 1661 Help Jimmy(DP)
- POJ 1661Help Jimmy(dp)
- POJ 1661 Help Jimmy(dp)
- POJ 1661 Help Jimmy(DP,注意边界)
- poj 1661 help Jimmy(dp)
- DP-POJ-1661-Help Jimmy
- poj 1661 Help Jimmy(dp)
- poj 1661 Help Jimmy(DP:记忆化搜索)
- POJ - 1661 Help Jimmy(DP)
- M - Help Jimmy POJ - 1661 ——dp
- POJ 1661 Help Jimmy——树形dp
- POJ 1661 Help Jimmy(DP,注意边界)
- POJ 1661 Help Jimmy(动态规划)
- poj1661——Help Jimmy//最短路
- POJ 1661 Help Jimmy(动态规划--最短下降模板)
- poj1661:Help&nbsp;Jimmy
- [POJ](1661)Help Jimmy ---- 动态规划
- POJ 1611 Help Jimmy(DP,坑)
- Help Jimmy POJ - 1661