NYOJ-284 坦克大战

坦克大战

时间限制:1000 ms  |  内存限制:65535 KB

难度:3

描述

Many of us had played the game "Battle city" in our childhood, and some people (like me) even often play it on computer now.
What we are discussing is a simple edition of this game. Given a map that consists of empty spaces, rivers, steel walls and brick walls only. Your task is to get a bonus as soon as possible suppose that no enemies will disturb you (See the following picture).


Your tank can't move through rivers or walls, but it can destroy brick walls by shooting. A brick wall will be turned into empty spaces when you hit it, however, if your shot hit a steel wall, there will be no damage to the wall. In each of your turns, you can choose to move to a neighboring (4 directions, not 8) empty space, or shoot in one of the four directions without a move. The shot will go ahead in that direction, until it go out of the map or hit a wall. If the shot hits a brick wall, the wall will disappear (i.e., in this turn). Well, given the description of a map, the positions of your tank and the target, how many turns will you take at least to arrive there?

输入

The input consists of several test cases. The first line of each test case contains two integers M and N (2 <= M, N <= 300). Each of the following M lines contains N uppercase letters, each of which is one of 'Y' (you), 'T' (target), 'S' (steel wall), 'B' (brick wall), 'R' (river) and 'E' (empty space). Both 'Y' and 'T' appear only once. A test case of M = N = 0 indicates the end of input, and should not be processed.

输出

For each test case, please output the turns you take at least in a separate line. If you can't arrive at the target, output "-1" instead.

样例输入

3 4
YBEB
EERE
SSTE
0 0

样例输出

8

只能上下左右移动,射击时不可以移动

S代表刚墙,R代表河,这两样东西不可以通过

B代表砖墙,砖墙可以用子弹打破,因此通过砖墙需要消耗两步数

E代表空白,可以随意通过

Y代表初始位置,T代表目标位置

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
using namespace std;
char map[305][305];
//用来记录地图
int visited[305][305];
//用来标记地图
int n,m;
int bx,by,bz;
int ans;
int d[4][2]= {0,1,0,-1,1,0,-1,0};
//四个方向行走的坐标,一次只能单方向的走动

struct node
{
	int x,y,num;
	friend bool operator <(node a,node b)
	//定义优先级,步数少的优先
	{
		return a.num >b.num ;
	}
} now,temp;

int check(int a,int b)
//用来判断输入的坐标是否满足条件
{
	if(a>=n||a<0||b>=m||b<0||map[a][b]=='S'||map[a][b]=='R'||visited[a][b])
		//坐标如果出地图或者碰到刚墙和河以及该坐标点已经走过,则该坐标无效
		return 0;
	return 1;
}

void bfs()
{
	priority_queue<node> q;
	//建立优先队列
	now.x =bx;
	now.y =by;
	now.num =0;
	//存入初始信息(位置和回合数)
	visited[bx][by]=1;
	//将起始点标记
	q.push(now);
	while(!q.empty())
		//队列为空时跳出循环
	{
		temp=q.top() ;
		q.pop() ;
		//取出优先队列队顶元素
		for(int i=0; i<4; i++)
		{
			now.x =temp.x+d[i][0];
			now.y =temp.y+d[i][1];
			//向四个方向移动
			if(map[now.x][now.y]=='T')
				//当找到终点时
			{
				bz=1;
				//标记终点,用于最后输出
				ans=temp.num+1;
				//得走到终点,因此回合数需要+1
				return ;
			}
			else if(check(now.x ,now.y ))
				//当坐标位置满足判断时
			{
				if(map[now.x][now.y]=='B')
					//当前面是砖墙时
					now.num=temp.num+2;
				//因为砖墙需要额外射击一回合,因此如果碰到砖墙移动回合需要+2
				else
					now.num=temp.num+1;
				//没有特殊情况就+1回合
				visited[now.x][now.y]=1;
				//标记当前坐标点
				q.push(now);
			}
		}
	}
}

int main()
{
	while(~scanf("%d%d",&n,&m)&&n&&m)
	{
		for(int i=0; i<n; i++)
		{
			scanf("%s",map[i]);
			//因为是一行直接输出下来的,所以直接储存一行
			for(int j=0; j<m; j++)
			{
				if(map[i][j]=='Y')
					//记录起始点的坐标
				{
					bx=i;
					by=j;
				}
			}
		}
		memset(visited,0,sizeof(visited));
		//初始化标记数组
		bz=0;
		//做一个判断变量
		bfs();
		if(bz)
			printf("%d\n",ans);
		else
			printf("-1\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yxy602843889/article/details/81907930