题意解析:其实就是判断起始点能否到达终止点。如果起始点和终止点值不同,直接输出NO。bfs,dfs都行。
附加条件:①不能出边界
②不能走值为0的点
③路径不能转向两次以上
节点需要记录该点的坐标,方向,转向次数。下面是BFS代码(注意剪枝:超过两次的就不要再加入队列了)
#include<iostream> #include<cstdio> #include<queue> #define M 1005 using namespace std; int G[M][M]; int Hash[M][M]; //记录某条路径在该点转向的次数 int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}}; int n,m; struct Node { int x,y,d,turn; }; queue<Node>q; bool bfs(int x1,int y1,int x2,int y2) { Node p,t; while(!q.empty()){ p=q.front(); q.pop(); if(p.x==x2&&p.y==y2&&p.turn<=2) return true; //满足条件 for(int i=0;i<4;i++){ t.x=p.x+dir[i][0]; t.y=p.y+dir[i][1]; if(t.x<1||t.y<1||t.x>n||t.y>m) continue; //出边界情况 if(p.d==i){ t.turn=p.turn; t.d=p.d; } else{ t.turn=p.turn+1; t.d=i; } if(t.turn>2) continue; //转向次数超过两次的(剪枝) if((!G[t.x][t.y]||(t.x==x2&&t.y==y2))&&Hash[t.x][t.y]>=t.turn){ q.push(t); Hash[t.x][t.y]=t.turn; } } } return false; } int main() { //freopen("d:\\Test.txt","r",stdin); int x1,x2,y1,y2; while(scanf("%d%d",&n,&m)&&(n||m)){ for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&G[i][j]); } } int Q; scanf("%d",&Q); for(int i=0;i<Q;i++){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(G[x2][y2]!=G[x1][y1]||G[x1][y1]==0||G[x2][y2]==0||(x1==x2&&y1==y2)){ cout<<"NO"<<endl; continue; } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ Hash[i][j]=11;//初始为较大的数即可 } } Hash[x1][y1]=0; //出发点 while(!q.empty()) q.pop(); Node t; //初始出发点4个方向的值 for(int i=0;i<4;i++){ t.d=i; t.turn=0; t.x=x1; t.y=y1; q.push(t); } if(bfs(x1,y1,x2,y2)) cout<<"YES"<<endl; else cout<<"NO"<<endl; } } return 0; }
时间: 2024-10-13 01:30:48