【SSL】1786麻将游戏
Time Limit:1000MS
Memory Limit:65536K
Description
在一种"麻将"游戏中,游戏是在一个有W*H格子的矩形平板上进行的。每个格子可以放置一个麻将牌,也可以不放(如图所示)。玩家的目标是将平板上的所有可通过一条路径相连的两张相同的麻将牌,从平板上移去。最后如果能将所有牌移出平板,则算过关。
这个游戏中的一个关键问题是:两张牌之间是否可以被一条路径所连接,该路径满足以下两个特性:
1. 它由若干条线段组成,每条线段要么是水平方向,要么是垂直方向。
2. 这条路径不能横穿任何一个麻将牌 (但允许路径暂时离开平板)。
这是一个例子:
在(1,3)的牌和在(4, 4)的牌可以被连接。(2, 3)和(3, 4)不能被连接。
你的任务是编一个程序,检测两张牌是否能被一条符合以上规定的路径所连接。
Input
输入文件的第一行有两个整数w,h (1<=w,h<=75),表示平板的宽和高。接下来h行描述平板信息,每行包含w个字符,如果某格子有一张牌,则这个格子上有个’X’,否则是一个空格。平板上最左上角格子的坐标为(1,1),最右下角格子的坐标为(w,h)。接下来的若干行,每行有四个数x1, y1, x2, y2 ,且满足1<=x1,x2<=w,1<=y1,y2<=h,表示两张牌的坐标(这两张牌的坐标总是不同的)。如果出现连续四个0,则表示输入结束。
Output
输出文件中,对于每一对牌输出占一行,为连接这一对牌的路径最少包含的线段数。如果不存在路径则输出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。
向4个方向扩展。
每个方向,如果能走就一直走下去。
如果没有访问过,加入队列。
如果到达终点,输出答案。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
int n,m,x,y,zx,zy,fs[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
bool d[1010][1010],a[1010][1010];
struct jgt
{
int x,y,s;
};
void input()
{
int i,j;
char t;
memset(a,true,sizeof(a));
scanf("%d%d",&m,&n);
for(i=1;i<=n;i++)
{
getchar();
for(j=1;j<=m;j++)
{
if (getchar()=='X')
a[i][j]=0;
}
}
return;
}
void BFS()
{
queue<jgt> b;
int dx,dy,i;
jgt t;
d[x][y]=0;
for(t.x=x,t.y=y,t.s=0,b.push(t);!b.empty();b.pop())
{
for(i=0;i<4;i++)//四个方向
{
for(dx=b.front().x+fs[i][0],dy=b.front().y+fs[i][1];0<=dx&&dx<=n+1&&0<=dy&&dy<=m+1&&a[dx][dy];dx+=fs[i][0],dy+=fs[i][1])//不停走下去
{
if(d[dx][dy])
{
d[dx][dy]=0;
t.x=dx,t.y=dy,t.s=b.front().s+1;
b.push(t);//加入
}
}
if(dx==zx&&dy==zy)//到达终点
{
printf("%d\n",b.front().s+1);
return;
}
}
}
printf("0\n");
return;
}
int main()
{
input();
scanf("%d%d%d%d",&y,&x,&zy,&zx);
while(x||y||zx||zy)
{
memset(d,true,sizeof(d));
BFS();
scanf("%d%d%d%d",&y,&x,&zy,&zx);
}
return 0;
}