POJ1661(KB12-M DP)
Help Jimmy
Description
"Help Jimmy" 是在下图所示的场景上完成的游戏。
场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。
Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。
设计一个程序,计算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恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。
Jimmy的大小和平台的厚度均忽略不计。如果Jimmy恰好落在某个平台的边缘,被视为落在平台上。所有的平台均不重叠或相连。测试数据保证问题一定有解。
Output
对输入的每组测试数据,输出一个整数,Jimmy到底地面时可能的最早时间。
Sample Input
1 3 8 17 20 0 10 8 0 10 13 4 14 3
Sample Output
23
Source
1 //2017-04-06 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 7 using namespace std; 8 9 const int inf = 0x3f3f3f3f; 10 struct node{ 11 int l, r, h; 12 bool operator<(const node x) 13 { 14 return this->h > x.h; 15 } 16 }platform[1005]; 17 int dpl[1005], dpr[1005];//dpl[i]记录从第i块平台左端点落地所需的最短时间,dpr[i]记录从第i块平台右端点落地所需的最短时间 18 int n, MAX; 19 20 int dfs(int x, int y, int ptr)//输入参数表示从第ptr块平台,位于(x, y)点开始搜索 21 { 22 if(dpl[ptr] != inf && dpr[ptr] != inf) 23 if(y-platform[ptr].h <= MAX) 24 if(platform[ptr].l <= x && platform[ptr].r >= x) 25 return y-platform[ptr].h+min(dpl[ptr]+x-platform[ptr].l, dpr[ptr]+platform[ptr].r-x);//记忆化搜索,返回位于(x, y)点向左右走的最短时间 26 int l, r, h; 27 for(int i = ptr; i < n; i++){ 28 l = platform[i].l; 29 r = platform[i].r; 30 h = platform[i].h; 31 if(h <= y && y-h <= MAX){ 32 if(x >= l && x <= r){ 33 if(h == 0)return y-h; 34 else{ 35 int left = dfs(l, h, i+1);//向左走 36 dpl[i] = min(dpl[i], left); 37 int right = dfs(r, h, i+1);//向右走 38 dpr[i] = min(dpr[i], right); 39 return y-h+min(dpl[i]+x-l, dpr[i]+r-x); 40 } 41 } 42 } 43 } 44 return inf; 45 } 46 47 int main() 48 { 49 int T, x, y, ans; 50 scanf("%d", &T); 51 while(T--) 52 { 53 scanf("%d%d%d%d", &n, &x, &y, &MAX); 54 for(int i = 0; i < n; i++){ 55 scanf("%d%d%d", &platform[i].l, &platform[i].r, &platform[i].h); 56 dpl[i] = dpr[i] = inf; 57 } 58 //加入地面这一块平台,高度为0,左右边界无穷 59 platform[n].h = 0; 60 platform[n].l = -inf; 61 platform[n].r = inf; 62 dpl[n] = dpr[n] = inf; 63 n++; 64 sort(platform, platform+n); 65 int l, r, h, i; 66 for(i = 0; i < n; i++)//找到下落遇到的地一块平台,从这块平台开始搜索 67 { 68 l = platform[i].l; 69 r = platform[i].r; 70 h = platform[i].h; 71 if(h <= y && y-h <= MAX) 72 if(x >= l && x <= r) 73 break; 74 } 75 ans = dfs(x, h, i)+y-h; 76 printf("%d\n", ans); 77 } 78 79 return 0; 80 }