ZOJ2925 DomiNo Grid(广搜)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2925


DomiNo Grid

Time Limit: 2 Seconds       Memory Limit: 65536 KB

Dominoes are small, flat, rectangular-shaped game pieces. Domino pieces are usually twice as long as they are wide and are usually made to be exactly half as thick as they are wide so that they can stand on edge without falling over. If we push one end of a queue of dominoes, the whole queue will fall over.


Now, you will be given some descriptions of domino grid with a '.' indicating an open space and an uppercase 'X' indicating a domino and the force used on one domino. You are to compute the ending descriptions. The force consists of two parts : location and direction. There are 8 directions shown below.

direction abbreviation
West : W
NorthWest : V
North : N
NorthEast : Y
East : E
SouthEast : Q
South : S
SouthWest : J

The falling direction of the pushed domino is always the same as the force. Other dominoes will fall over if: 1) it's adjacent with a previous fallen domino. 2) it's within 45 degree of the falling direction of the previous domino.

The direction of falling is the relative position of it to the previous fallen domino. No two dominoes will cause the same domino to fall over simultaneously. See the following example for more details.

XXX
XXX
XXX

We say the outer 8 dominoes are adjacent with the middle one. With a force to east on the middle domino, the 3 dominoes in the third column will fall over and the direction will be northeast, east, southeast. So the ending grid is :

XXY
XEE
XXQ

Input

There are multiple test cases. Each case begins with a line containing two positive integer n and m (1 <= n, m <= 500) that are the number of rows and columns of the grid. The next n lines each with m chars (only '.' and 'X') describe one row of the grid. At last, two integers i, j (ith row, jth column, both i and j start from 1) indicate the location of the force and a char C describes the direction of the force. You can assume that there is a domino at the location (i, j).

Process to the end of file.

Output

Print the ending description of the grid, using the abbreviations for the fallen dominoes.

Print a blank line between cases.

Sample Input

2 4
..XX
XX..
1 3 S
4 4
XXX.
...X
X..X
XXX.
3 1 E

Sample Output

..SX
WJ..

WWV.
...N
E..Y
XQE.


题意:在n*m的矩形场地上,X表示多米诺骨牌,.表示空地。推到一个多米诺骨牌可以影响与它相邻且夹角在45度以内的多米诺骨牌,分别倒向相应的方向
(如题中,向右推最中间的骨牌,影响右上(倒向右上),右(倒向右),右下(倒向右下))
现在告诉你场地情况,并在某个位置施加向某个方向的力(保证那个位置有骨牌),问最终场地的情况。

直接从施力的点进行广度优先搜索即可。难度主要在于影响的位置的判断与被影响的骨牌的倒的方向。(还有表示各个方向的神奇字母)
用了一个函数qfx来判断出骨牌可以影响的3个位置,然后分别搜索三个位置的情况。
可以发现,特定位置的骨牌倒的方向是一定的,即如果位于前一个骨牌右上角的骨牌受到影响,那么一定会倒向右上角。可以以此减少判断语句的数量。
(如果采用合适的下标对应方法可以省去求方向的switch语句以及判断倒下方向的if语句)

注意:输出格式,最后一组数据输出时不要空行。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;

const int mxn=100005;
int zfx[3][2];

char  g[505][505];
int  q[mxn][2];
int n,m,xx0,yy0;
char fx;

void qfx(int ux,int uy)//求出ux,uy倒下方向所能影响到的位置
{
	switch (g[ux][uy])
		{
		case 'W':
			zfx[0][0]=-1;zfx[0][1]=-1;
			zfx[1][0]=0;zfx[1][1]=-1;
			zfx[2][0]=1;zfx[2][1]=-1;
			break;
		case 'V':
			zfx[0][0]=-1;zfx[0][1]=0;
			zfx[1][0]=-1;zfx[1][1]=-1;
			zfx[2][0]=0;zfx[2][1]=-1;
			break;
		case 'N':
			zfx[0][0]=-1;zfx[0][1]=1;
			zfx[1][0]=-1;zfx[1][1]=0;
			zfx[2][0]=-1;zfx[2][1]=-1;
			break;
		case 'Y':
			zfx[0][0]=-1;zfx[0][1]=0;
			zfx[1][0]=-1;zfx[1][1]=1;
			zfx[2][0]=0;zfx[2][1]=1;
			break;
		case 'E':
			zfx[0][0]=-1;zfx[0][1]=1;
			zfx[1][0]=0;zfx[1][1]=1;
			zfx[2][0]=1;zfx[2][1]=1;
			break;
		case 'Q':
			zfx[0][0]=0;zfx[0][1]=1;
			zfx[1][0]=1;zfx[1][1]=1;
			zfx[2][0]=1;zfx[2][1]=0;
			break;
		case 'S':
			zfx[0][0]=1;zfx[0][1]=0;
			zfx[1][0]=1;zfx[1][1]=-1;
			zfx[2][0]=1;zfx[2][1]=1;
			break;
		case 'J':
			zfx[0][0]=0;zfx[0][1]=-1;
			zfx[1][0]=1;zfx[1][1]=-1;
			zfx[2][0]=1;zfx[2][1]=0;
			break;
		default:
			printf("ERROR!\n");
		}
}
void bfs(int x,int y)//广搜,节省空间用了循环队列
{
	int head=0,tail=0,cnt=0;
	q[tail][0]=x;q[tail][1]=y;tail=(tail+1)%mxn;++cnt;
	while (cnt>0)
	{
		int ux=q[head][0],uy=q[head][1];
		--cnt;head=(head+1)%mxn;
		qfx(ux,uy);
		for (int i=0;i<3;i++)
		{
			int nx=ux+zfx[i][0],ny=uy+zfx[i][1];
			if (nx<1||ny<1||nx>n||ny>m||g[nx][ny]=='.') continue;
			
			if (g[nx][ny]=='X')//如果影响到了骨牌,就把骨牌位置入队,同时标上骨牌倒下的方向
			{
				q[tail][0]=nx;q[tail][1]=ny;tail=(tail+1)%mxn;++cnt;
				if (zfx[i][0]==1)
				{
						if (zfx[i][1]==1) {g[nx][ny]='Q';}
						else if (zfx[i][1]==0) {g[nx][ny]='S';}
						else g[nx][ny]='J';
				}
				if (zfx[i][0]==0)
				{
					if (zfx[i][1]==1) {g[nx][ny]='E';}
					else if (zfx[i][1]==-1) {g[nx][ny]='W';}
				}
				if (zfx[i][0]==-1)
				{
					if (zfx[i][1]==1) g[nx][ny]='Y';
					else if (zfx[i][1]==0) g[nx][ny]='N';
					else g[nx][ny]='V';
				}
			}
		}
	}
}

int main()
{
	int ca=0;
	while (scanf("%d%d",&n,&m)!=EOF)
	{
		++ca;
		memset(g,0,sizeof(g));
		for (int i=1;i<=n;i++)
		{
			scanf("%s",g[i]+1);
		}
		scanf("%d%d",&xx0,&yy0);
		cin>>fx;
		g[xx0][yy0]=fx;
		bfs(xx0,yy0);
		if (ca!=1) printf("\n");//控制输出格式
		for (int i=1;i<=n;i++)
		{
			printf("%s\n",g[i]+1);
		}
		
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值