第二个处理附带转折问题的题目
分析:
1.开始时就直接判断 如果起点处和目标点处数字不同,或则起点或终点有一个是0,直接no。
2.因为限定了最小转向次数,所以采用bfs单向搜,hdu 1728与之及其类似
代码:
/*
Note:
分析:
1.单方向BFS判断转折点,两次转折转折次数为3,从-1开始为2
2.一开始时就开始判断,如果起始点有一个是0或则起始点数字不同,则不需要受伤
*/
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<iostream>
using namespace std;
//#define test
const int maxn = 1000+2;
int G[maxn][maxn];
int n,m;
const int dx[]={-1,0,1,0}; // 上 右 下 左
const int dy[]={0,1,0,-1};
int vis[maxn][maxn];
bool ok;
struct point{
int x,y,cnt;
}s,e;
bool check(int x,int y){
return (x>=0 && x<n && y>=0 && y<m &&( G[x][y]==0 || ( x==e.x && y==e.y )))?true:false;
}
void bfs(){ //一个方向搜到底
queue<point> q;
s.cnt=-1;
q.push(s);
vis[s.x][s.y]=1;
int cnt;
while(!q.empty()){
point now = q.front(); q.pop();
for(int i=0;i<4;i++){
point t;
t.x=now.x+dx[i];
t.y=now.y+dy[i];
while( check(t.x,t.y) ){
if(!vis[t.x][t.y]){
vis[t.x][t.y]=1;
t.cnt=now.cnt+1;
q.push(t);
if(t.x==e.x && t.y==e.y && t.cnt<=2){ // 转折次数不超过两次相当于转3次
ok=true;
return ;
}
}
t.x=t.x+dx[i], t.y=t.y+dy[i]; // 继续一个方向搜
}
}
}
}
int main(){
#ifdef test
freopen("test.txt","r",stdin);
#endif
while(scanf("%d%d",&n,&m)!=EOF && n+m){
memset(G,0,sizeof(G));
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&G[i][j]);
int q;
scanf("%d",&q);
for(int i=0;i<q;i++){
ok=false;
memset(vis,0,sizeof(vis));
scanf("%d%d%d%d",&s.x,&s.y,&e.x,&e.y);
s.x-- , s.y-- , e.x-- , e.y--;
if((G[s.x][s.y]!=G[e.x][e.y]) || G[s.x][s.y]==0 || G[e.x][e.y]==0){
printf("NO\n");
continue;
}
bfs();
if(ok)
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}