题意:如下图所示,蜘蛛侠在某个位置,他女朋友在另一个建筑(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 ", DP()); 58 } 59 return 0; 60 }