#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
#define MAXN 1005
//用于保存点信息的结构
typedef struct _node
{
int x, y; //坐标信息
unsigned short change; //转弯次数信息
int dic; //点的方向信息
}node;
int cmap[MAXN][MAXN]; //保存图信息
int vistied[MAXN][MAXN]; //记录点是否已访问过
int flag; //标识点是否可消除
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; //用于保存4个方向的数组
int m, n;
int xs, ys, xe, ye;
int legal(int x, int y); //判断点是否合法
void bfs(int sx, int sy); //广搜算法
int main(void)
{
int i, j, q;
while (scanf("%d %d", &m, &n) && (m + n))
{
memset(cmap, -1, sizeof(cmap));
//构图
for (i=1; i<=m; i++)
{
for (j=1; j<=n; j++)
{
scanf("%d", &cmap[i][j]);
}
}
scanf("%d", &q);
while (q--)
{
flag = 0;
memset(vistied, 0, sizeof(vistied));
scanf("%d%d%d%d", &xs, &ys, &xe, &ye);
//如果所选点值或起始点和结尾点为0则表示无法消除
if (cmap[xs][ys] != cmap[xe][ye] || cmap[xs][ys] == 0 || cmap[xe][ye] == 0)
{
printf("NO/n");
}
else
{
bfs(xs, ys);
if (flag)
{
printf("YES/n");
}
else
{
printf("NO/n");
}
}
}
}
return 0;
}
int legal(int x, int y)
{
if (x<0 || x>m || y<0 || y>n)
{
return 0;
}
return 1;
}
//广搜算法
void bfs(int sx, int sy)
{
queue<node> que; //用于保存合法点的队列
node p, t;
int i;
p.x = sx; //初始化节点
p.y = sy;
p.change = 0;
p.dic = -1;
t.dic = -1;
t.change = 0;
vistied[p.x][p.y] = 1;
que.push(p); //将起始节点入队
while (!que.empty())
{
p = que.front();
que.pop();
//出队节点如果和结束节点位置相同则表示可以删除,计算结束
if (p.x == xe && p.y == ye)
{
flag = 1;
break;
}
for (i=0; i<4; i++)
{
t.x = p.x + dir[i][0];
t.y = p.y + dir[i][1];
//用于改变节点转弯次数信息和方向信息
if (p.dic != -1)
{
if (p.dic != i)
{
t.change = p.change + 1;
}
else
{
t.change = p.change;
}
}
else
{
t.change = 0;
}
t.dic = i;
//转弯次数小于等于2且点合法且未被访问过,点值为0或者该点是结束点则符合条件入队
if (t.change <=2 && legal(t.x, t.y) && !vistied[t.x][t.y]
&& (cmap[t.x][t.y] == 0 || (t.x == xe && t.y == ye)))
{
que.push(t);
vistied[t.x][t.y] = 1;
}
}
}
}
本文介绍了一种使用广搜算法解决特定图中消除特定点问题的方法,通过构建图、判断点合法性、实现广搜算法并判断是否可以消除目标点,最后输出是否可行的结论。

被折叠的 条评论
为什么被折叠?



