pku 1925 Spiderman DP
http://poj.org/problem?id=1925
题意:
蜘蛛侠的女朋友被坏人抓到了 tower (目标点),他必须尽快从 apartment(起点)到tower去救人,给出n个建筑物的坐标以及高度(第一个为起点最后一个为目标点),求蜘蛛侠用蜘蛛网最少荡几次才能到达tower?注意:这里在起点之后的建筑物保证高度都会大于等于起点的高度。
思路:
首先计算每个点i的来源点j的取值范围,然后枚举这个范围,递归的求解。假设来源点为j 则有x[i] - sqrt(h[i]*h[i] - (h[i] - H)*(h[i] - H)) <= j < x[i]; 其中x[i]为i建筑物的坐标,h[i]为i建筑物高度,H为h[0],注意这里在蜘蛛侠的每个停留点他的高度必为h[0](对称性)枚举来源点后计算有j可能到达的点pos = 2*(x[i] - j) + j = 2*x[i] - j;即可:
PS:注意再用sqrt()求解释h[i]*h[i]会超数据类型,所以我使用了double型,你也可以直接用三角函数求解这样就不用考虑超数据类型的了。
View Code
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <cmath> #define CL(a,num) memset(a,num,sizeof(a)) #define maxn 5007 #define N 1000004 using namespace std; const int inf = 1999999; int dp[N]; int x[maxn]; double h[maxn]; int n; int main() { //freopen("din.txt","r",stdin); int i,j,t; scanf("%d",&t); while (t--) { scanf("%d",&n); for (i = 0; i < n; ++i) scanf("%d%lf",&x[i],&h[i]); CL(dp,-1); dp[x[0]] = 0; double H = h[0]; int ans = inf; for (i = 1; i < n; ++i)//枚举每个建筑物 { double tmp = sqrt((h[i]*h[i]*1.0 - 1.0*(h[i] - H)*(h[i] - H))*1.0); int l = x[i] - (int)tmp;//计算可能的来源点 for (j = max(x[0],l); j < x[i]; ++j)//枚举来源点 { if (dp[j] != -1) { if (2*x[i] - j >= x[n -1])//2*x[i] - j就是可能到达的点 { ans = min(ans,dp[j] + 1); } else if (dp[2*x[i] - j] == -1 || dp[2*x[i] - j] > dp[j] + 1) dp[2*x[i] - j] = dp[j] + 1; } } } if (ans != inf) printf("%d\n",ans); else printf("-1\n"); } return 0; }