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;

}

 

 

你可能感兴趣的:(spider)