<题目链接>
题目大意:
在一个棋盘上给定一个起点和终点,判断这两点是否能通过连线连起来,规定这个连线不能穿过其它的棋子,并且连线转弯不能超过2次。
解题分析:
就是DFS从起点开始搜索,只不过搜索的时候需要记录当前的方向和已经转弯的次数,然后通过题目给定的限制条件进行搜索,判断是否存在从起点到终点转弯次数不超过2次的连线。同时,在转弯次数达到两次的时候,我们可以对搜索树进行可行性剪枝,直接判断转弯两次后,该点与终点是否在同一条直线上,从而减少搜索时间。
#include <bits/stdc++.h> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) const int N= 1e3+5; int mpa[N][N],vis[N][N]; int n,m,sx,sy,ex,ey; const int dir[][2]={1,0,0,1,-1,0,0,-1}; bool fp; void dfs(int x,int y,int nowdir,int cnt){ vis[x][y]=1; if(cnt>2||fp)return; if(x==ex&&y==ey){ fp=true;return; } for(int k=0;k<4;k++){ int cnt1=cnt; int nx=x+dir[k][0],ny=y+dir[k][1]; if(nx<1||nx>n||ny<1||ny>m||vis[nx][ny])continue; if((nx==ex&&ny==ey)||!mpa[nx][ny]){ if((nowdir!=-1)&&nowdir!=k){ cnt1++;if(cnt1==2){ if((nx-ex)!=0&&(ny-ey)!=0)return; //如果第二次转弯与终点不在同一条直线上 else{ //转了2次后,判断该点是否能够通过这条直线到达终点 int xx=nx,yy=ny; while(xx>=1||xx<=n||yy>=1||yy<=m){ if(xx==ex&&yy==ey){ fp=true; return; } //如果通过该直线能够直接到达终点 if(mpa[xx][yy]!=0)return; //如果中途除终点外有障碍物 xx=xx+dir[k][0],yy=yy+dir[k][1]; //沿着这条直线往前走 } } } } dfs(nx,ny,k,cnt1); } } } int main(){ while(~scanf("%d%d",&n,&m),n||m){ rep(i,1,n) rep(j,1,m) scanf("%d",&mpa[i][j]); int q;scanf("%d",&q); while(q--){ scanf("%d%d%d%d",&sx,&sy,&ex,&ey); if(sx<1||sx>n||sy<1||sy>m||ex<1||ex>n||ey<1||ey>m||(sx==ex&&sy==ey)){puts("NO");continue;} //判断这两点的位置合不合法 fp=false; memset(vis,0,sizeof(vis)); if(mpa[sx][sy]==mpa[ex][ey]&&mpa[sx][sy])dfs(sx,sy,-1,0); //如果起点终点相同,且有棋子 fp?puts("YES"):puts("NO"); } } }
AC代码:
#include <bits/stdc++.h> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) const int N = 1e3+5; int mpa[N][N]; bool vis[N][N]; int n,m,q,sx,sy,ex,ey; bool flag; const int dicx[]={1,-1,0,0}; const int dicy[]={0,0,1,-1}; void dfs(int x,int y,int dic,int cnt){ if(cnt>2||flag) return; //转弯次数大于2或者已经找到就终止 if(cnt==2&&(x-ex)!=0&&(y-ey)!=0) return;//剪枝:判断两次转弯后是否与目标在同一直线上 if(x==ex&&y==ey){ flag=true;return; } for(int k=0;k<4;++k){ int xx=x+dicx[k],yy=y+dicy[k]; if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]) continue; if(mpa[xx][yy]==0||(xx==ex&&yy==ey)){ vis[xx][yy]=1; if(dic==-1||dic==k)dfs(xx,yy,k,cnt); else dfs(xx,yy,k,cnt+1); vis[xx][yy]=0; } } } int main(){ while(~scanf("%d%d",&n,&m),n||m){ rep(i,1,n) rep(j,1,m) scanf("%d",&mpa[i][j]); scanf("%d",&q); while(q--){ scanf("%d%d%d%d",&sx,&sy,&ex,&ey); memset(vis,0,sizeof(vis)); flag=false; if(mpa[sx][sy]==mpa[ex][ey]&&mpa[sx][sy])dfs(sx,sy,-1,0); //初始方向置为-1 flag?puts("YES"):puts("NO"); } } }