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
", cal());
55     }
56     return 0;
57 }
原文地址:https://www.cnblogs.com/bfshm/p/3828951.html