題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1175
連連看
Problem Description
“連連看”相信很多人都玩過。沒玩過也沒關係,下面我給大家介紹一下遊戲規則:在一個棋盤中,放了很多的棋子。如果某兩個相同的棋子,可以通過一條線連起來(這條線不能經過其它棋子),而且線的轉折次數不超過兩次,那麼這兩個棋子就可以在棋盤上消去。不好意思,由於我以前沒有玩過連連看,諮詢了同學的意見,連線不能從外面繞過去的,但事實上這是錯的。現在已經釀成大禍,就只能將錯就錯了,連線不能從外圍繞過。
玩家鼠標先後點擊兩塊棋子,試圖將他們消去,然後遊戲的後臺判斷這兩個方格能不能消去。現在你的任務就是寫這個後臺程序。
Input
輸入數據有多組。每組數據的第一行有兩個正整數n,m(0
/* 這道題和逃離迷宮是一樣的套路,廣搜套深搜,這個轉彎的次數是固定的。
在逃離迷宮的基礎上多了幾個條件需要滿足:
1.起點和終點不能重合
2.起點和終點必須類型一樣(即所代表的數字一樣)
3.所給起點終點所代表的數字都不能是0,因爲0表示這個地方沒有棋子。*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
int to[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
int n,m,x1,y1,x2,y2,q;
int map[1005][1005];
int vis[1005][1005];
struct node
{
int x;
int y;
int turn;
}pre,now;
int check(int ex,int ey)
{
if(ex>=0&&ex<n&&ey>=0&&ey<m)
return 0;
return -1;
}
void bfs()
{
queue<node>q;
pre.x=x1;
pre.y=y1;
pre.turn=-1;
vis[pre.x][pre.y]=1;
q.push(pre);
while(!q.empty())
{
pre=q.front();
q.pop();
if(pre.turn>=2)
{
printf("NO\n");
return;
}
for(int i=0;i<4;i++)
{
now.x=pre.x+to[i][0];
now.y=pre.y+to[i][1];
now.turn=pre.turn+1;
while(1)
{
if(check(now.x,now.y)==0&&(map[now.x][now.y]==0||now.x==x2&&now.y==y2))
{//第一次錯在了now.x==x2&&now.y==y2這個條件的判斷上,
//我最初寫的是map[now.x][now.y]==map[x2][y2]
if(now.x==x2&&now.y==y2&&now.turn<=2)
{
printf("YES\n");
return;
}
if(!vis[now.x][now.y])
{
vis[now.x][now.y]=1;
q.push(now);
}
now.x=now.x+to[i][0];
now.y=now.y+to[i][1];
}
else
break;
}
}
}
printf("NO\n");
return;
}
int main()
{
while(scanf("%d %d",&n,&m),n!=0||m!=0)
{
for(int i=0;i<n;i++)
{
getchar();
for(int j=0;j<m;j++)
scanf("%d",&map[i][j]);
}
scanf("%d",&q);
while(q--)
{
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
y1-=1;
x1-=1;
y2-=1;
x2-=1;
memset(vis,0,sizeof(vis));
//下面幾個條件判斷是比逃離迷宮多出來的判斷
if(map[x1][y1]!=map[x2][y2])
printf("NO\n");
else if(map[x1][y1]==0||map[x2][y2]==0)
printf("NO\n");
else if(x1==x2&&y1==y2)
printf("NO\n");
else
bfs();
}
}
return 0;
}