I - 连连看
“连连看”相信很多人都玩过。没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子。如果某两个相同的棋子,可以通过一条线连起来(这条线不能经过其它棋子),而且线的转折次数不超过两次,那么这两个棋子就可以在棋盘上消去。不好意思,由于我以前没有玩过连连看,咨询了同学的意见,连线不能从外面绕过去的,但事实上这是错的。现在已经酿成大祸,就只能将错就错了,连线不能从外围绕过。
玩家鼠标先后点击两块棋子,试图将他们消去,然后游戏的后台判断这两个方格能不能消去。现在你的任务就是写这个后台程序。
直接上码
#include<stdio.h>
#include<string.h>
#include<queue>
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
int fx[4][2]= {{0,1},{1,0},{0,-1},{-1,0}}; //重点:方向数组必须是顺时针或者逆时针
int p[1005][1005];
int vis[1005][1005][4];
int n,m,ax,ay,bx,by;
bool check(int x,int y)
{
if(x>=1&&y>=1&&x<=n&&y<=m)
return true;
return false;
}
struct node
{
int x,y,t,f;
};
bool ff;
void bfs()
{
queue<node>q;
node start;
start.x=ax;
start.y=ay;
start.f=-1; //当前方向
start.t=-1; //转弯次数
q.push(start);
while(!q.empty())
{
node net;
net=q.front();
q.pop();
if(net.x==bx&&net.y==by)
{
ff=true;
}
for(int i=0; i<4; i++)
{
node net2;
net2.x=net.x+fx[i][0];
net2.y=net.y+fx[i][1];
if(i==net.f)
{
net2.t=net.t; //当前步与上一步同向,不转弯
net2.f=i;
}
else
{
net2.t=net.t+1; //当前步与上一步不同向,转弯次数+1
net2.f=i;
}
if(net2.t>2)continue; //转弯次数大于2时 不存在放入队列的可能
if(check(net2.x,net2.y))
{
if(!p[net2.x][net2.y]||(net2.x==bx&&net2.y==by))
{
if(!vis[net2.x][net2.y][i])
{
vis[net2.x][net2.y][i]=1;
q.push(net2); //满足以上条件 放入队列
}
}
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m)&&n+m)
{
int i,j,v;
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
scanf("%d",&p[i][j]);
scanf("%d",&v);
while(v--)
{
mem(vis,0);
scanf("%d%d%d%d",&ax,&ay,&bx,&by);
if(p[ax][ay]!=p[bx][by]||!p[ax][ay]||!p[bx][by])
{
printf("NO\n");
continue;
}
ff=false;
bfs();
printf(ff?"YES\n":"NO\n");
}
}
}