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
解题思路
和之前写的一道最小拐弯问题几乎一样,只是把输入改了,还有输出最少段数,段数=拐弯+1
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int way[4][2]={{0,-1},{-1,0},{1,0},{0,1}};
int v[100100][2],h,t;
int a[100][100],n,m,b[100][100],s[100][100];
int sx,sy,ex,ey;
bool check(int x,int y){
return (x>=0&&x<=n+1&&y>=0&&y<=m+1);//可以出矩阵
}
void BFS(int x,int y,int x1,int y1){//可以看我最小拐弯的注释
a[x1][y1]=0,b[x][y]=1;
h=0,t=1,v[1][0]=x,v[1][1]=y;
while(h++<t){
for(int i=0;i<4;i++){
int xx=v[h][0]+way[i][0],yy=v[h][1]+way[i][1];
while(check(xx,yy)&&!a[xx][yy]){
if(!b[xx][yy]){
v[++t][0]=xx,v[t][1]=yy,b[xx][yy]=1;
s[xx][yy]=s[v[h][0]][v[h][1]]+1;
if(xx==x1&&yy==y1)return;
}
xx+=way[i][0],yy+=way[i][1];
}
}
}
}
int main(){
scanf("%d%d",&m,&n);
char c=getchar();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char c=getchar();
if(c=='X')a[i][j]=1;
}
char c=getchar();
}//输入字符
scanf("%d%d%d%d",&sy,&sx,&ey,&ex);
while(sx){
memset(s,0,sizeof(s));
memset(b,0,sizeof(b));//记得清零
memset(v,0,sizeof(v));
BFS(sx,sy,ex,ey);
a[ex][ey]=1;
if(b[ex][ey])printf("%d\n",s[ex][ey]);//输出最少段数
else printf("0\n");
scanf("%d%d%d%d",&sy,&sx,&ey,&ex);//while输入
}
}