POJ 1925 DP

Spiderman
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 6719 Accepted: 1340
Description

Dr. Octopus kidnapped Spiderman’s girlfriend M.J. and kept her in the West Tower. Now the hero, Spiderman, has to reach the tower as soon as he can to rescue her, using his own weapon, the web.

From Spiderman’s apartment, where he starts, to the tower there is a straight road. Alongside of the road stand many tall buildings, which are definitely taller or equal to his apartment. Spiderman can shoot his web to the top of any building between the tower and himself (including the tower), and then swing to the other side of the building. At the moment he finishes the swing, he can shoot his web to another building and make another swing until he gets to the west tower. Figure-1 shows how Spiderman gets to the tower from the top of his apartment – he swings from A to B, from B to C, and from C to the tower. All the buildings (including the tower) are treated as straight lines, and during his swings he can’t hit the ground, which means the length of the web is shorter or equal to the height of the building. Notice that during Spiderman’s swings, he can never go backwards.

You may assume that each swing takes a unit of time. As in Figure-1, Spiderman used 3 swings to reach the tower, and you can easily find out that there is no better way.
Input

The first line of the input contains the number of test cases K (1 <= K <= 20). Each case starts with a line containing a single integer N (2 <= N <= 5000), the number of buildings (including the apartment and the tower). N lines follow and each line contains two integers Xi, Yi, (0 <= Xi, Yi <= 1000000) the position and height of the building. The first building is always the apartment and the last one is always the tower. The input is sorted by Xi value in ascending order and no two buildings have the same X value.
Output

For each test case, output one line containing the minimum number of swings (if it’s possible to reach the tower) or -1 if Spiderman can’t reach the tower.
Sample Input

2
6
0 3
3 5
4 3
5 5
7 4
10 4
3
0 3
3 4
10 4
Sample Output

3
-1

题意:

蜘蛛侠要从第一个楼不断的吐丝跳跃到最后一个楼,每次跳跃都会跳到对称的位置。求最小的跳跃次数。如果最后都无法跳到,输出-1;

题解:

可以看出蜘蛛侠的高度不论怎么跳都是固定的(除了跳到最后一个柱子)。
我们枚举每一个柱子的位置,然后判断从第一柱子到当前枚举的柱子间的位置是否跳到过,如果跳到过那么对称的位置+1.如果对称的位置超过了最后一个柱子则特殊处理一下。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <string>
#include <set>
#include <cmath>
#include <map>
#include <queue>
#include <sstream>
#include <vector>
#include <iomanip>
#define m0(a) memset(a,0,sizeof(a))
#define mm(a) memset(a,0x3f,sizeof(a))
#define m_1(a) memset(a,-1,sizeof(a))
#define f(i,a,b) for(i = a;i<=b;i++)
#define fi(i,a,b) for(i = a;i>=b;i--)
#define lowbit(a) ((a)&(-a))
#define FFR freopen("data.in","r",stdin)
#define FFW freopen("data.out","w",stdout)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef long double ld;
const ld PI = acos(-1.0);

using namespace std;
#define SIZE (5000+20)

struct Po
{
    int x, y;
};

Po a[SIZE];
ll b[SIZE];
int dp[1000000*2 + 10];
//int p[1000000 + 10];
int n;

inline bool IsTrue(const Po& a, const Po& b) {
    if ((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y) <= b.y*b.y)
        return true;
    return false;
}

int main()
{
    //ios_base::sync_with_stdio(false); cin.tie(0);
    int N;
    scanf("%d", &N);
    while (N--)
    {
        scanf("%d", &n);
        int i, j,k;
        f(i, 1, n) {
            scanf("%d%d", &(a[i].x), &(a[i].y));
            b[i] = a[i].y*a[i].y - (a[1].y - a[i].y)*(a[1].y - a[i].y);
        }

        m_1(dp);
        dp[a[1].x] = 0;
        f(i, 2, n) {
            //int kk = a[i].x - a[i].y>=0? a[i].x - a[i].y :0;
            fi(j, a[i].x-1, a[1].x) {
                if (dp[j] != -1) {

                    if ((j-a[i].x)*(j - a[i].x)<=b[i]) {
                        int aim = 2 * a[i].x - j;
                        if (dp[aim] == -1 || dp[aim] > dp[j] + 1)
                            dp[aim] = dp[j] + 1;
                        if (aim >= a[n].x)
                            if (dp[a[n].x] == -1 || dp[a[n].x] > dp[j]+1)
                                dp[a[n].x] = dp[j] + 1;
                    }
                    else
                        break;
                }
            }
        }
        printf("%d\n", dp[a[n].x]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值