poj 1925 Spiderman (dp)
这道题也是想了好长时间了, 一直没有写出来,想过一下思路,都wa了,看了题解以后才明白的。
题意:给定N个柱子,现在要在这N个柱子之间摇摆,直至到达最右端的那一个柱子,问最少要
摇摆多少次. 摇摆的时机是在开始的时候或者是从某一点摇摆到某个对称的点时,保证所有的柱子的高度不低于出发点的高度.
分析:d[i]代表横坐标i 的最小的步数,先要计算每个楼房的范围,因为在摇摆的时候不能低于地面。
所以在坐标范围内枚举以每个楼房为支点的坐标, 找一个最小的。
注意Long long。
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <cmath> 5 #include <cstdio> 6 #include <algorithm> 7 #define LL long long 8 using namespace std; 9 const int maxn = 1000000 + 10; 10 const int INF = 1<<28; 11 int d[maxn], n; 12 struct node 13 { 14 LL x, y, ran; 15 }p[5000 + 10]; 16 17 int cal() 18 { 19 int i, j, a, b, tmp, ans = INF; 20 for(i = 0; i < maxn; i++) 21 d[i] = INF; 22 d[p[1].x] = 0; 23 for(i = 2; i <= n; i++) 24 { 25 a = p[i].x - p[i].ran; b = p[i].x; 26 if(a < 0) 27 a = 0; 28 for(j = a; j < b; j++) //以这个楼房为支点的范围 29 { 30 tmp = p[i].x + p[i].x-j; 31 if(tmp >= p[n].x) //已经到达最后一个。 32 ans = min(ans, d[j]+1); 33 else 34 d[tmp] = min(d[tmp], d[j]+1); 35 } 36 } 37 return ans == INF?-1:ans; 38 } 39 int main() 40 { 41 int i; 42 LL tmp; 43 int t; 44 scanf("%d", &t); 45 while(t--) 46 { 47 scanf("%d", &n); 48 for(i = 1; i <= n; i++) 49 { 50 scanf("%d%d", &p[i].x, &p[i].y); 51 tmp = p[i].y - p[1].y; 52 p[i].ran = sqrt(p[i].y*p[i].y - tmp*tmp); //每个楼房的范围 53 } 54 printf("%d\n", cal()); 55 } 56 return 0; 57 }