UVa 1600 Patrol Robot(三维广搜)
A robot has to patrol around a rectangular area which is in a form of m x n grid (m rows and ncolumns). The rows are labeled from 1 to m. The columns are labeled from 1 to n. A cell (i, j)denotes the cell in row i and column j in the grid. At each step, the robot can only move from one cell to an adjacent cell, i.e. from (x, y) to (x + 1, y), (x, y + 1), (x - 1, y) or (x, y - 1). Some of the cells in the grid contain obstacles. In order to move to a cell containing obstacle, the robot has to switch to turbo mode. Therefore, the robot cannot move continuously to more than k cells containing obstacles.
Your task is to write a program to find the shortest path (with the minimum number of cells) from cell (1, 1) to cell (m, n). It is assumed that both these cells do not contain obstacles.
Input
The input consists of several data sets. The first line of the input file contains the number of data sets which is a positive integer and is not bigger than 20. The following lines describe the data sets.
For each data set, the first line contains two positive integer numbers m and n separated by space(1≤m, n≤20). The second line contains an integer number k (0≤k≤20). The ith line of the next m lines contains n integer aij separated by space (i = 1, 2,..., m;j = 1, 2,..., n). The value ofaij is 1 if there is an obstacle on the cell (i, j), and is 0 otherwise.
Output
For each data set, if there exists a way for the robot to reach the cell (m, n), write in one line the integer number s, which is the number of moves the robot has to make; -1 otherwise.
Sample Input
3
2 5
0
0 1 0 0 0
0 0 0 1 0
4 6
1
0 1 1 0 0 0
0 0 1 0 1 1
0 1 1 1 1 0
0 1 1 1 0 0
2 2
0
0 1
1 0
Simple Output
7
10
-1
题意
机器人从起点(0,0)走到(m,n),图中有障碍,机器人最多连续翻越k个障碍,求走到(m,n)的最短路径长度
题解1
一开始在二维上想怎么连续,而且已经访问过的点有可能再访问(本来的连续大),最后硬着头皮想了个蠢方法(if去判断)
代码1
1 #include<bits/stdc++.h> 2 using namespace std; 3 int Map[25][25],Cnt[25][25];//Map的值为连续越过的数量,Cnt的值为步数 4 int dx[]={0,0,1,-1}; 5 int dy[]={1,-1,0,0}; 6 int n,m,k; 7 struct Node 8 { 9 int x,y; 10 Node(int x=1,int y=1):x(x),y(y){} 11 }; 12 int bfs() 13 { 14 queue<Node> qu; 15 Cnt[1][1]=0; 16 qu.push(Node(1,1)); 17 Node h,t; 18 while(!qu.empty()) 19 { 20 h=qu.front(); 21 qu.pop(); 22 if(h.x==n&&h.y==m)return Cnt[n][m]; 23 for(int i=0;i<4;i++) 24 { 25 t.x=h.x+dx[i]; 26 t.y=h.y+dy[i]; 27 if(t.x>=1&&t.x<=n&&t.y>=1&&t.y<=m) 28 { 29 //h表示当前,t表示下一个 30 if(Map[t.x][t.y]!=0&&Map[h.x][h.y]!=0)//当前和下一个!=0表示连续 31 if(Cnt[t.x][t.y]==-1)//未访问过 32 Map[t.x][t.y]=Map[h.x][h.y]+1;//下一个连续=当前连续+1 33 else if(Map[t.x][t.y]>Map[h.x][h.y]+1)//若已访问过,如果下一个已经有的连续>当前+1 34 { 35 Map[t.x][t.y]=Map[h.x][h.y]+1;//保证当前连续为最小连续,为了下一步走得更舒服 36 Cnt[t.x][t.y]=-1;//标记未访问 37 } 38 if(Map[t.x][t.y]!=0&&Map[h.x][h.y]==0)//表示这是第一个连续 39 if(Cnt[t.x][t.y]==-1)//未访问过 40 Map[t.x][t.y]=1;//这个点为初始连续1 41 else if(Map[t.x][t.y]>1)//若已访问过,如果下一个连续不是初始连续1,设为初始连续1 42 { 43 Map[t.x][t.y]=1;//保证当前连续为最小连续,为了下一步走得更舒服 44 Cnt[t.x][t.y]=-1;//标记未访问 45 } 46 if(Map[t.x][t.y]<=k&&Cnt[t.x][t.y]==-1)//连续<=k,未访问 47 { 48 Cnt[t.x][t.y]=Cnt[h.x][h.y]+1; 49 qu.push(t); 50 } 51 //上面处理的很蠢 52 } 53 } 54 } 55 return -1; 56 } 57 int main() 58 { 59 //freopen("in.txt","r",stdin); 60 //freopen("out.txt","w",stdout); 61 int t; 62 scanf("%d",&t); 63 while(t--) 64 { 65 memset(Cnt,-1,sizeof(Cnt)); 66 scanf("%d%d%d",&n,&m,&k); 67 for(int i=1;i<=n;i++) 68 for(int j=1;j<=m;j++) 69 scanf("%d",&Map[i][j]); 70 printf("%d\n",bfs()); 71 } 72 return 0; 73 }
题解2
后来发现可以用三维广搜去写,增加的第三维表示到这个点[X,Y]步数为STEP的情况
代码2
1 #include<bits/stdc++.h> 2 using namespace std; 3 int Map[25][25],Cnt[25][25],Vis[25][25][25];//Vis[x][y][step] 4 int dx[]={0,0,1,-1}; 5 int dy[]={1,-1,0,0}; 6 int n,m,k; 7 struct Node 8 { 9 int x,y,step;//step为连续数 10 Node(int x=1,int y=1,int step=0):x(x),y(y),step(step){} 11 }; 12 int bfs() 13 { 14 queue<Node> qu; 15 Cnt[1][1]=0; 16 Vis[1][1][0]=1; 17 qu.push(Node(1,1,0)); 18 Node h,t; 19 while(!qu.empty()) 20 { 21 h=qu.front();qu.pop(); 22 if(h.x==n&&h.y==m)return Cnt[n][m]; 23 for(int i=0;i<4;i++) 24 { 25 t.x=h.x+dx[i]; 26 t.y=h.y+dy[i]; 27 t.step=h.step; 28 if(t.x>=1&&t.x<=n&&t.y>=1&&t.y<=m) 29 { 30 if(Map[t.x][t.y]==1)t.step=h.step+1;//墙,连续+1 31 else t.step=0;//不是墙,连续=0 32 if(t.step<=k&&Vis[t.x][t.y][t.step]==0)//连续<=k并且未访问 33 { 34 Vis[t.x][t.y][t.step]=1;//标记访问 35 if(Cnt[t.x][t.y]==-1)//未走到过(第一次走到的肯定是最小路径) 36 Cnt[t.x][t.y]=Cnt[h.x][h.y]+1; 37 qu.push(t); 38 } 39 } 40 } 41 } 42 return -1; 43 } 44 int main() 45 { 46 //freopen("in.txt","r",stdin); 47 //freopen("out.txt","w",stdout); 48 int t; 49 scanf("%d",&t); 50 while(t--) 51 { 52 memset(Cnt,-1,sizeof(Cnt)); 53 memset(Vis,0,sizeof(Vis)); 54 scanf("%d%d%d",&n,&m,&k); 55 for(int i=1;i<=n;i++) 56 for(int j=1;j<=m;j++) 57 scanf("%d",&Map[i][j]); 58 printf("%d\n",bfs()); 59 } 60 return 0; 61 }