麻将游戏【BFS】

麻将游戏

Time Limit:10000MS Memory Limit:65536K
Total Submit:237 Accepted:86
Case Time Limit:1000MS


Description
  在一种"麻将"游戏中,游戏是在一个有 W * H W*H WH格子的矩形平板上进行的。每个格子可以放置一个麻将牌,也可以不放(如图所示)。玩家的目标是将平板上的所有可通过一条路径相连的两张相同的麻将牌,从平板上移去。最后如果能将所有牌移出平板,则算过关。
  这个游戏中的一个关键问题是:两张牌之间是否可以被一条路径所连接,该路径满足以下两个特性:
  1. 它由若干条线段组成,每条线段要么是水平方向,要么是垂直方向。
  2. 这条路径不能横穿任何一个麻将牌 (但允许路径暂时离开平板)。
  这是一个例子:
  在这里插入图片描述
  在 ( 1 , 3 ) (1,3) 13的牌和在 ( 4 , 4 ) (4, 4) (4,4)的牌可以被连接。 ( 2 , 3 ) (2, 3) (2,3) ( 3 , 4 ) (3, 4) (3,4)不能被连接。
  你的任务是编一个程序,检测两张牌是否能被一条符合以上规定的路径所连接。


Input
  输入文件的第一行有两个整数 w , h ( 1 < = w , h < = 75 ) w,h (1<=w,h<=75) wh1<=wh<=75,表示平板的宽和高。接下来 h h h行描述平板信息,每行包含 w w w个字符,如果某格子有一张牌,则这个格子上有个 ′ X ′ 'X' X,否则是一个空格。平板上最左上角格子的坐标为 ( 1 , 1 ) (1,1) 11,最右下角格子的坐标为 ( w , h ) (w,h) w,h。接下来的若干行,每行有四个数 x 1 , y 1 , x 2 , y 2 x1, y1, x2, y2 x1y1x2y2,且满足 1 < = x 1 , x 2 < = w , 1 < = y 1 , y 2 < = h 1<=x1,x2<=w,1<=y1,y2<=h 1<=x1,x2<=w1<=y1,y2<=h,表示两张牌的坐标(这两张牌的坐标总是不同的)。如果出现连续四个 0 0 0,则表示输入结束。

Output
  输出文件中,对于每一对牌输出占一行,为连接这一对牌的路径最少包含的线段数。如果不存在路径则输出 0 0 0


Sample Input
5 4
XXXXX
X (三个空格) X
XXX (一个空格)X
(一个空格) XXX (一个空格)
2 3 5 3
1 3 4 4
2 3 3 4
0 0 0 0

Sample Output
4
3
0


解题思路

很明显,这又又…又是一道BFS,(毕竟作者还在学)让我们求对牌的路径最少包含的线段数。。。
其实就是 最小转弯问题 答案加一。。
小小的变化:
1. 1. 1.字符输入, ‘ X ’ ‘X’ X 1 1 1 ‘ ’ ‘ ’ 0 0 0
2. 2. 2.要注意“允许路径暂时离开平板“”。
3. 3. 3.每个数据输出后要给一些标记的数组清零。


代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int dx[5]={0,0,1,0,-1};
const int dy[5]={0,1,0,-1,0};
int n,m,a,b,c,d,bsy[200][200];
int st[300000][4],fa[200][200];
int h=0,t=1,ans;
int s;
bool check(int x,int y)
{
	if(x>=0&&x<=n+1&&y>=0&&y<=m+1&&!bsy[x][y])如果碰到墙就结束拓展,但可超出平板一圈
	return 1;
	else
	return 0;
}
void bfs(){
	h=0; t=1;
	st[1][1]=a;
	st[1][2]=b;	
	st[1][3]=0;
	bsy[c][d]=0; //一定记得要给终点解封
	fa[a][b]=1;
	do{
		h++;
		for(int k=1;k<=4;k++)
		{
		    int xx,yy;
		    xx=st[h][1]; yy=st[h][2];
		    while(check(xx+dx[k],yy+dy[k]))
		    {
		    	if(!fa[xx+dx[k]][yy+dy[k]])
		    	{ //如果已经走过的路线就不入队
		    	  t++;
			      st[t][1]=xx+dx[k];//储存位置
			      st[t][2]=yy+dy[k];//储存位置
		          st[t][3]=st[h][3]+1;//储存转弯数
		          fa[xx+dx[k]][yy+dy[k]]=1;//标记已经走过该地
			      if(st[t][1]==c&&st[t][2]==d)//结束判断
			      {
			      	 s=st[t][3];
			      	 return;
			      }
		    	}
		    	xx+=dx[k]; yy+=dy[k];
		    }
		}
	}while(h<t);
}
int main(){
	scanf("%d%d",&m,&n);
	for(int i=1;i<=n;i++)//字符读入
	{
		char c=getchar();
		for(int j=1;j<=m;j++){
			char c=getchar();
			if(c=='X') 
			bsy[i][j]=1;
		else
			bsy[i][j]=0;
	    }
	}
	scanf("%d%d%d%d",&b,&a,&d,&c);
	while(a)
	{
		s=0;
		bfs(); 
		if(fa[c][d])cout<<s<<endl;
		   else 
		   cout<<0<<endl;
		memset(fa, 0, sizeof(fa));
	    bsy[c][d]=1;//重新给终点封锁
		scanf("%d%d%d%d",&b,&a,&d,&c);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值