codeforces 793B - Igor and his way to work(dfs、bfs)
题目链接:http://codeforces.com/problemset/problem/793/B
题目大意:告诉你起点和终点,要求你在只能转弯两次的情况下能不能到达终点。能就输出“YES”,不能就输出“NO”。
解题思路:这算是经典的转弯题了,接近半年没写搜索题了,,所以今天先拿这道题开刀吧。这个题关键就是“判重”,如何记录走过的点。我们可以开个三维数组,记录各个坐标各个方向上的转弯数,如果下次在到这个点这个方向,那就比较转弯数,如果这次转弯数大于等于已经记录的转弯数那就不用再找下去了,因为这次能走到的地方,上次肯定也能走到。估计一下时间复杂度大概为O(4*3n)。
dfs:
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int N=1e3+5; 5 int m,n; 6 bool flag=false; 7 char map[N][N]; 8 int vis[N][N][5];//*关键*用来标记走过的点,记录该点朝着各方向转弯数 9 int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; 10 11 void dfs(int x,int y,int dir,int cnt){ 12 if(x<=0||x>m||y<=0||y>n||cnt>2) 13 return; 14 if(vis[x][y][dir]<=cnt)//如果这个位置这个方向已经走过,且用了更小的转弯数,那就不用再走这个点了 15 return; 16 if(map[x][y]=='T'){ 17 flag=true; 18 return; 19 } 20 if(map[x][y]!='.'&&map[x][y]!='S') 21 return; 22 vis[x][y][dir]=cnt; 23 for(int i=0;i<4;i++) { 24 int x1=x+d[i][0]; 25 int y1=y+d[i][1]; 26 if(dir==-1) 27 dfs(x1,y1,i,cnt); 28 else if(dir!=i) 29 dfs(x1,y1,i,cnt+1); 30 else 31 dfs(x1,y1,i,cnt); 32 } 33 } 34 35 int main(){ 36 int index,indey; 37 scanf("%d %d",&m,&n); 38 getchar(); 39 for(int i=1;i<=m;i++){ 40 for(int j=1;j<=n;j++){ 41 scanf("%c",&map[i][j]); 42 if(map[i][j]=='S'){ 43 index=i; 44 indey=j; 45 } 46 } 47 getchar(); 48 } 49 memset(vis,0x3f,sizeof(vis));//转弯数初始化为无限大 50 dfs(index,indey,-1,0);//-1表示开始位置没有方向 51 if(flag) 52 printf("YES\n"); 53 else 54 printf("NO\n"); 55 }
bfs,跟上面差不多的:
1 #include<iostream> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 const int N=1e3+5; 6 int vis[N][N][5]; 7 int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; 8 char map[N][N]; 9 int m,n; 10 bool flag=false; 11 12 struct node{ 13 int x,y,dir,cnt; 14 }now,t,pre; 15 //int num=0; 16 void bfs(int stax,int stay){ 17 queue<node>q; 18 t.x=stax; 19 t.y=stay; 20 t.dir=-1; 21 t.cnt=0; 22 q.push(t); 23 while(!q.empty()){ 24 pre=q.front(); 25 q.pop(); 26 for(int i=0;i<4;i++){ 27 int x=pre.x+d[i][0]; 28 int y=pre.y+d[i][1]; 29 int cnt; 30 if(pre.dir==-1)//判断一下上次方向和当前要走的方向的关系 31 cnt=0; 32 else if(pre.dir==i) 33 cnt=pre.cnt; 34 else if(pre.dir!=i) 35 cnt=pre.cnt+1; 36 if(x<=0||x>m||y<=0||y>n||cnt>2) 37 continue; 38 if(map[x][y]=='T'){//到达终点 39 flag=true; 40 return; 41 } 42 if(map[x][y]!='S'&&map[x][y]!='.') 43 continue; 44 if(vis[x][y][i]<=cnt)//这个点这个方向已经有更优方案了 45 continue; 46 vis[x][y][i]=cnt; 47 now.x=x; 48 now.y=y; 49 now.dir=i; 50 now.cnt=cnt; 51 // num++; 52 // printf("%d\n",num); 53 q.push(now); 54 } 55 } 56 } 57 int main(){ 58 int index,indey; 59 scanf("%d %d",&m,&n); 60 getchar(); 61 for(int i=1;i<=m;i++){ 62 for(int j=1;j<=n;j++){ 63 scanf("%c",&map[i][j]); 64 if(map[i][j]=='S'){ 65 index=i; 66 indey=j; 67 } 68 } 69 getchar(); 70 } 71 memset(vis,0x3f,sizeof(vis)); 72 bfs(index,indey); 73 if(flag) 74 printf("YES\n"); 75 else 76 printf("NO\n"); 77 }