问题描述:http://acm.hdu.edu.cn/showproblem.php?pid=1175
思路很清晰,但是因为实现的方式和代码的问题,纠结了好久,最后请牛人(YWJ)帮忙,终于好了。
采用广度搜索,队列实现,先入先出,实现的时候,关键是对走过的路径的标识,防止陷入死循环。用数组has[][]标记一个点最小的拐角数。还有设立方向数组op[][],只要一个for就解决了四个方向,防止代码的重复。当然要注意判断下一步压入队列的和当前位置的关系,到底有没有拐角等。还有当拐角大于2时直接无视掉。
程序代码:
#include<iostream> #include<queue> using namespace std; int res[1010][1010];//保存数组 int has[1010][1010];//标记到该节点最少的拐角(重点。。。) int op[4][2]={-1,0,1,0,0,1,0,-1}; struct node { int x; int y; int step;//标记拐角数 int id;//标记方向,-1直走,0,1,2,3分别是向上,下,右,左 }; queue<node> myQue; bool run(int x1,int y1,int x2,int y2,int n,int m) { int i,j; int x,y; node temp,now; for(i=1;i<=n;i++) for(j=1;j<=m;j++) has[i][j]=5; while(!myQue.empty()) myQue.pop(); temp.x=x1; temp.y=y1; temp.step=-1; temp.id=-1; myQue.push(temp); has[x1][y1]=-1; while(!myQue.empty()) { temp=myQue.front(); myQue.pop(); //如果前一步不是直走到,那么按其直走的方向走一步。因为额for循环中没有走。 for(i=0;i<4;i++) { //如果拐弯数大于等于二的时候不能拐弯 if(temp.step>=2&&temp.id!=i) continue; x=temp.x+op[i][0]; y=temp.y+op[i][1]; if(x==x2&&y==y2) return true; if(x<1||x>n||y<1||y>m) continue; if(res[x][y]!=0) continue; now.x=x; now.y=y; if(i==temp.id) { now.step=temp.step; now.id=temp.id; }else{ now.id=i; now.step=temp.step+1; } //若经过该点的拐角数比保存的要小,则入队列 if(has[now.x][now.y]>=now.step) { has[now.x][now.y]=now.step; myQue.push(now); } } } return false; } int main(int argc, char* argv[]) { int n,m; int i,j; int t,a,b,c,d; while(cin>>n>>m) { if(n==0&&m==0) break; for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>res[i][j]; cin>>t; while(t--) { cin>>a>>b>>c>>d; if(res[a][b]==0||res[c][d]==0||(a==c&&b==d)) { cout<<"NO"<<endl; continue; } if(res[a][b]!=res[c][d]) cout<<"NO"<<endl; else if(run(a,b,c,d,n,m)) cout<<"YES"<<endl; else cout<<"NO"<<endl; } } return 0; }