【POJ 1925】 Spiderman(dp)

【POJ 1925】 Spiderman(dp)


Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 6806 Accepted: 1361

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


最近卡在各种题上,各种不爽。。。昨天开始啃这题,最后也没A,今天搞了搞印象笔记,不得不说,是个好APP,。金巨安利给窝的,后来又跟金巨请教了请教数论相关的知识


刚刚想起来这题,打算接着啃,结果瞟了一眼,立马发现有个Int,感觉会乘爆,甚至确定是这里的问题了……改了交了发,果然=.=



扯远了,这题题意:一个王子or骑士or狂战士or蝙蝠侠or蜘蛛侠。。。恩,蜘蛛侠比较像

在最左边的城堡顶端,公主or......,。在最右端的。。。恩……塔中。。。

现在蜘蛛侠要去救公主,每次他可以选择一个塔顶作为支点,然后荡到右边同高度的未知,也就是右移相同的横坐标(如图所示


规定荡下来不可以着地,也就是绳子要小于等于作为支点的塔高。


问最少需要经过几个塔。如果不存在合法的方案,输出-1。

题目保证第一个塔是起点,并且之后的塔都高于或同高于第一个塔。





题目很友好了……然而卡了一下午不友好的代码……只怪不够强=。=

刚开始我是枚举横坐标,然后找后面的塔,如果合法,就通过这个塔荡过去(更新右边到达的地方的塔数

这样是n*m的,,炸掉了

后来换过来,枚举塔,然后从最左可行的起点到该塔,挨个荡过去,WA。。。

然后今天把一处的int改成long long就过了=.=人生如梦%…………

另外要注意,题目中到达公主塔的定义是碰到即可


代码如下:

#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread() freopen("in.in","r",stdin)
#define fwrite() freopen("out.out","w",stdout)

using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const int mod = 1e9+7;
const double eps = 1e-8;

int dp[2000100];
pair <LL,LL> pr[5555];

int main()
{
	//fread();
	//fwrite();

	int t,n,h,pos,mn,nt;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		memset(dp,-1,sizeof(dp));
		//读取蜘蛛侠所在塔位置和高度
		scanf("%d%d",&pos,&h);

		for(int i = 1; i < n; ++i)
			scanf("%lld%lld",&pr[i].first,&pr[i].second);

		dp[pos] = 0;
		mn = INF;
		//枚举塔
		for(int i = 1; i < n; ++i)
		{
			//printf("x:%lld y:%lld\n",pr[i].first,pr[i].second);
			//就是这里…………#¥%#¥%¥#%
			LL x = pr[i].first;
			LL y = pr[i].second;

			//枚举左边可行的起点
			for(int j = max(pos,(int)x-(int)sqrt((y*y-(y-h)*(y-h))*1.0)); j < x; ++j)
			{
				//printf("dp[%d]:%d\n",pos,dp[pos]);
				if(dp[j] == -1) continue;

				nt = pr[i].first*2-j;
				//printf("%d/%lld\\%d\n",pos,pr[j].first,nt);
				//如果能荡到最右边的塔
				if(nt >= pr[n-1].first)
				{
					mn = min(mn,dp[j]+1);
				}else if(dp[nt] == -1 || dp[nt] > dp[j]+1) dp[nt] = dp[j]+1;
			}
		}
		printf("%d\n",mn == INF? -1: mn);
	}

	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值