【英雄】解题报告

2英雄(hero.cpp/pas)


题目描述(Description):

城堡迷宫由N×M个格子组成,英雄Mario玛丽奥要在城堡迷宫中从起始点移动到目标点去拯救被怪物掳去的公主,他每一步只能从当前所在的格子移动到相邻的4个格子之一,而且不能移出城堡的范围,走一步需要1秒的时间。

城堡中某些格子里面有弹簧,每个弹簧具有特定的能量K,不同弹簧的K值不一定相同。如果Mario跳到一个有弹簧的格子,他就会继续向前跳,直到Mario跳到一个空的格子或者被墙所阻挡无法继续向前。

10











◎:Mario :公主 ▲:弹簧

示例一:Mario现所在位置是(2,8),有一个弹簧在(2,7),能量值为5,则Mario只需向左走一步,就会被弹到(2,2),从(2,8)(2,2)Mario只需一步,即1秒。

示例二:Mario现所在位置是(2,8),有一个弹簧在(2,7),能量值为10,则Mario只需向左走一步,就会被弹到(2,1),从(2,8)(2,1)Mario只需一步,即1秒。

9











8











7










6











5











4











3











2









1












1

2

3

4

5

6

7

8

9

10


请你计算Mario从起始点到达目标点(公主位置)需要的最短时间,如果不能到达,输出“Impossible


输入文件(hero.in):

第一行,两个整数,NM3<=N,M<=100),分别表示城堡的行和列。

第二行,一个非负整数K,表示弹簧的数量。接下来K行,每行含3个正整数——XYP。其中XY是弹簧的坐标(2<=X<=N-12<=Y<=M-1),P是该弹簧的能量。

接下来最后两行,第一行是Mario的坐标,第二行是公主的坐标。

注意:输入文件保证没有一个弹簧是挨着城堡围墙的。

输出文件(hero.out):

输出Mario从初始位置到达公主所在位置需要的最短时间(秒)。

如果不能到达,则输出“Impossible。(引号不需输出)


样例(Sample):

SampleInput Case 1:

1010

1

2 75

2 8

1 1

SampleOutput Case 1:

3


又是一道当时没有AC的水题。就是一个宽搜,我觉得考试还是尽量采取不容易错的写法来写,避免一些看起来比较巧妙,其实容易出错的方法。

各种需要单独讨论的情况要分类清晰,避免盲目,避免混乱


这道题要注意弹簧可以无限踩,连续踩两次弹簧时间是1s。

//#include <iostream>
//using std::cout;
//using std::cin;
#include <cstdio>
#include <cstdlib>
const long oo = 0x7fff0000;

struct tnode 
{
	long x;
	long y;
	long t;
	long f;
};

const long MAX = 15000000; 
tnode que[MAX];

long map[102][102];
bool used[102][102];
long dx[4] = {-1,0,1,0};
long dy[4] = {0,1,0,-1};

long sx;long sy;
long tx;long ty;
long n;long m;long k;

void bfs()
{
	long l = 0;
	long r = 0;
	
	r++;
	que[r].x = sx;
	que[r].y = sy;
	que[r].t = 0;
	
	while (l!=r)
	{
		l = (l+1)%MAX;
		tnode* now = &que[l];
		for (long i=0;i<4;i++)
		{
			long nx = now->x+dx[i];
			long ny = now->y+dy[i];
			
			if (nx>0&&ny>0&&nx<n+1&&ny<m+1&&!used[nx][ny])
			{
				if (map[nx][ny]==0)
				{
					used[nx][ny] = true;
					r = (r+1)%MAX;
					que[r].x=nx;que[r].y=ny;que[r].t=now->t+1;
				}
				else if (map[nx][ny]>0)
				{
					while (nx>0&&ny>0&&nx<n&&ny<m&&map[nx][ny]>0)
					{
						long pow = map[nx][ny];
						nx += pow*dx[i];
						ny += pow*dy[i];
					}
					if (nx<=0)nx=1;
					if (ny<=0)ny=1;
					if (nx>n)nx=n;
					if (ny>m)ny=m;
					r = (r+1)%MAX;
					que[r].x=nx;que[r].y=ny;que[r].t=now->t+1;
					used[nx][ny] = true;
				}
				
				if (nx==tx&&ny==ty)
				{
					printf("%ld",que[r].t);
					exit(0);
				}
			}
		}
	}
}

int main()
{
	freopen("hero.in","r",stdin);
	freopen("hero.out","w",stdout);
	
	scanf("%ld%ld%ld",&n,&m,&k);
	for (long i=1;i<k+1;i++)
	{
		long x;long y;long p;
		scanf("%ld%ld%ld",&x,&y,&p);
		map[x][y] = p;
	}
	
	scanf("%ld%ld",&sx,&sy);
	scanf("%ld%ld",&tx,&ty);
	
	for (long i=0;i<n+2;i++)
	{
		map[i][0] = map[i][m+1] = -1;
	}
	for (long j=1;j<m+1;j++)
	{
		map[0][j] = map[n+1][j] = -1;
	}
	bfs();
	printf("Impossible");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值