POJ 1925 Spiderman

题意:如下图所示,蜘蛛侠在某个位置,他女朋友在另一个建筑(WestTower)上,蜘蛛侠每次可以吐丝到附近的建筑顶端,然后摇摆到关于该建筑物对称的位置。只要荡到横坐标 >= X(WestTower)的位置,就能爬上WestTower。问在不碰到地的情况下,最少要吐多少次丝。

解法:由于蜘蛛侠的纵坐标始终没变所以不需要记录纵坐标。对于每个建筑物,由于不能碰地所以只有一定的范围内能够吐丝到该建筑物并且移动,对每个建筑物,设这个范围为(l[i], r[i])。(l[i]和r[i]易求)

   设d[j]表示到达横坐标j所需要最少次数。枚举每个建筑物i,d[j] = min(d[j-k] + 1)(l[i] <= k <= r[i])。

tag:dp

 1 /*
 2  * Author:  Plumrain
 3  * Created Time:  2013-11-18 19:22
 4  * File Name: DP-POJ-1925.cpp
 5  */
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 #include <cmath>
10 #include <algorithm>
11 
12 using namespace std;
13 
14 #define CLR(x) memset(x, 0, sizeof(x))
15 const int maxint = 2147483647 - 10;
16 typedef long long int64;
17 
18 int n;
19 int x[5005], y[5005], d[1010005];
20 int64 a[5005];
21 
22 void init()
23 {
24     scanf ("%d", &n);
25     for (int i = 0; i < n; ++ i){
26         scanf ("%d%d", &x[i], &y[i]);
27         a[i] = (int64)y[i]*y[i] - (int64)(y[i]-y[0]) * (y[i]-y[0]);
28     }
29 }
30 
31 int DP()
32 {
33     for (int i = 0; i <= x[n-1]+10000; ++ i)
34         d[i] = maxint;
35     d[x[0]] = 0;
36 
37     for (int i = 1; i < n; ++ i){
38         for (int j = x[i]-1; j >= x[0]; -- j){
39             if ((int64)(x[i]-j)*(x[i]-j) > a[i]) break;
40 
41             int tmp = 2*x[i] - j;
42             if (tmp >= x[n-1])
43                 tmp = x[n-1];
44             d[tmp] = min(d[tmp], d[j] + 1);
45         }
46     }
47     
48     return d[x[n-1]] == maxint ? -1 : d[x[n-1]];
49 }
50 
51 int main()
52 {
53     int T;
54     scanf ("%d", &T);
55     while (T--){
56         init();
57         printf ("%d\n", DP());
58     }
59     return 0;
60 }
View Code

 

posted @ 2013-11-22 14:15  Plumrain  阅读(282)  评论(0编辑  收藏  举报