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;
}

 

 

posted @ 2012-08-13 14:25  E_star  阅读(240)  评论(0编辑  收藏  举报