1. 程式人生 > >【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;
}