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





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述 给出一个$n\times m$的矩阵,每个位置上有一个非负整数,代表这个位置的海拔高度。一开始时,有一个人站在其中一个位置上。这个人可以向上、下、左、右四个方向移动,但是只能移动到海拔高度比当前位置低或者相等的位置上。一次移动只能移动一个单位长度。定义一个位置为“山顶”,当且仅当从这个位置开始移动,可以一直走到海拔高度比它低的位置上。请问,这个矩阵中最多有多少个“山顶”? 输入格式 第一行两个整数,分别表示$n$和$m$。 接下来$n$行,每行$m$个整数,表示整个矩阵。 输出格式 输出一个整数,表示最多有多少个“山顶”。 样例输入 4 4 3 2 1 4 2 3 4 3 5 6 7 8 4 5 6 7 样例输出 5 算法1 (递归dp) $O(nm)$ 对于这道题,我们可以使用递归DP来解决,用$f(i,j)$表示以$(i,j)$为起点的路径最大长度,那么最后的答案就是所有$f(i,j)$中的最大值。 状态转移方程如下: $$ f(i,j)=\max f(x,y)+1(x,y)是(i,j)的下一个满足条件的位置 $$ 注意:这里的状态转移方程中的$x,y$是在枚举四个方向时得到的下一个位置,即: - 向上:$(i-1,j)$ - 向下:$(i+1,j)$ - 向左:$(i,j-1)$ - 向右:$(i,j+1)$ 实现过程中需要注意以下几点: - 每个点都需要搜一遍,因此需要用双重for循环来枚举每个起点; - 对于已经搜索过的点,需要用一个数组$vis$来记录,防止重复搜索; - 在进行状态转移时,需要判断移动后的点是否满足条件。 时间复杂度 状态数为$O(nm)$,每个状态转移的时间复杂度为$O(1)$,因此总时间复杂度为$O(nm)$。 参考文献 C++ 代码 算法2 (动态规划) $O(nm)$ 动态规划的思路与递归DP类似,只不过转移方程和实现方式有所不同。 状态转移方程如下: $$ f(i,j)=\max f(x,y)+1(x,y)是(i,j)的下一个满足条件的位置 $$ 注意:这里的状态转移方程中的$x,y$是在枚举四个方向时得到的下一个位置,即: - 向上:$(i-1,j)$ - 向下:$(i+1,j)$ - 向左:$(i,j-1)$ - 向右:$(i,j+1)$ 实现过程中需要注意以下几点: - 每个点都需要搜一遍,因此需要用双重for循环来枚举每个起点; - 对于已经搜索过的点,需要用一个数组$vis$来记录,防止重复搜索; - 在进行状态转移时,需要判断移动后的点是否满足条件。 时间复杂度 状态数为$O(nm)$,每个状态转移的时间复杂度为$O(1)$,因此总时间复杂度为$O(nm)$。 参考文献 C++ 代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值