题意:
判断两点之间是否可以通过至多有两次转变方向以达到相连,就是平时玩的连连看游戏,但是不能从外面绕过去。
思路:bfs,给每个加入的队列的点添加转变方向次数turn和点当前要走的方向dir属性,起点可以走四个方向。
参照代码来源:
我的代码,参照写得,加深练习和理解:
#include <iostream> #include <cstring> #include <queue> #include <cstdio> #include <cstdlib> using namespace std; const int M = 1005; int map[M][M]; int has[M][M]; struct node { int x,y; int turn; int dir; }; int dire[4][2] = {{0,1},{1,0},{0,-1},{-1,0}}; queue <node> q; int n,m; int sx,sy,ex,ey; struct node st; bool flag; inline bool in(const node &p) { if ((p.x<0 || p.y<0 || p.x>=n || p.y>=m)) return false; return true; } void bfs() { node now,t; while (!q.empty()) { now = q.front(); q.pop(); //cout << now.x << " " << now.y << " " << now.turn << " " << now.dir <<endl; if (now.x == ex && now.y == ey && now.turn<=2) //满足条件退出 { flag = true; return; } for (int i = 0; i < 4; i++) { if((now.dir+2)%4 == i) continue; t.x=now.x+dire[i][0],t.y=now.y+dire[i][1]; if(i == now.dir) //now的点和下一个走的点的方向相同 t.turn=now.turn,t.dir=now.dir; else t.turn=now.turn+1,t.dir=i; //if ((t.x>=0 && t.x < n && t.y>=0 && t.y<m) && (map[t.x][t.y] == 0|| (t.x == ex&&t.y == ey))&& (has[t.x][t.y]>=t.turn)) //如果不用in()函数的话我之前是这么写的 if (in(t) && (map[t.x][t.y] == 0|| (t.x == ex && t.y == ey))&& (has[t.x][t.y]>=t.turn) && t.turn <= 2) // 加入队列条件 { has[t.x][t.y] = t.turn; q.push(t); } } } } int main() { while (cin >> n >> m && n && m) { for (int i = 0;i < n;i++) { for (int j = 0;j < m;j++) cin >> map[i][j]; } int tt; cin >> tt; for (int i = 0;i < tt;i++) { cin >> sx >> sy >> ex >> ey; sx--,sy--,ex--,ey--; //printf("%d %d %d %d ",sx,sy,ex,ey); if ((sx == ex && sy == ey)|| map[sx][sy] == 0 || map[ex][ey] == 0 ||map[sx][sy] != map[ex][ey]) //判断输入的两点是否合法:是否相等,是否为0... { puts("NO"); continue; } for (int i = 0;i < n;i++) for (int j = 0;j < m;j++) has[i][j] = 111; while(!q.empty()) q.pop(); for (int i = 0;i < 4;i++) { st.x = sx,st.y = sy,st.turn = 0,st.dir = i; //起点的四个方向都要加入队列 q.push(st); } has[sx][sy] = 0; flag = false; bfs(); if(flag) cout << "YES "; else cout << "NO "; } } return 0; }