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(1m, n20). The second line contains an integer number k (0k20). 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
Sample Output
7 10 -1
题意:已知一个n*m的方格,0代表无障碍,1代表游障碍。无障碍的方格可以随便走,有障碍的方格最多连续走k个
求从左上角走到右下角的最短路径。如果不存在,输出-1;
思路:使用bfs,队列中存放的结构体中有当前位置的坐标,x,y,还有已经走过的步数member,以及连续走过的
障碍方格的个数countt. 对于下标不满足条件以及vis标记走过的方格,和连续走过方格的个数超过k的位置,都不放入
队列,反之放入队列,继续bfs,直至第一次到达右下角为止。
代码1:(使用二维数组标记,超时)
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef struct nodee{
int x,y,member,countt;
}node;
int ter[4][2]={1,0,0,1,-1,0,0,-1};
int maze[110][110],vis[110][110];
int n,m,k;
int bfs()
{
int i,xx,yy;
queue<node> q;
memset(vis,0,sizeof(vis));
node now,no;
now.x=0; now.y=0;
now.member=1; now.countt=0;
q.push(now);
vis[0][0]=1;
while(!q.empty()){
no=q.front();
q.pop();
if(no.x==n-1&&no.y==m-1)
return no.member-1;
for(i=0;i<4;i++){
now.x=no.x+ter[i][0];
now.y=no.y+ter[i][1];
if(now.x>=0 && now.x<n &&now.y>=0 &&now.y<m){
if(vis[now.x][now.y]==0){
vis[now.x][now.y]==1;
if(maze[now.x][now.y]==0){
now.member=no.member+1;
now.countt=0;
q.push(now);
}
else{
if((no.countt+1)<=k){
now.member=no.member+1;
now.countt=no.countt+1;
q.push(now);
}
}
}
}
}
}
return -1;
}
int main()
{ int f,i,j;
scanf("%d",&f);
while(f--){
scanf("%d %d %d",&n,&m,&k);
for(i=0;i<n;i++){
for(j=0;j<m;j++){
scanf("%d",&maze[i][j]);
}
}
printf("%d\n",bfs());
}
return 0;
}
因为每一个从平行的bfs状态下走到同一障碍方格时,可能之前连续走过的障碍方格的个数不同
所以,在同一位置,会有0~k不同的方格个数的选择,选用二维vis标记数组标记,情况考虑不全的同时还会超时。
所以,使用三维vis 标记数组标记,多出的一维用来记录该方格之前连续走过的障碍方格的个数。
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef struct nodee{
int x,y,member,countt;
}node;
int ter[4][2]={1,0,0,1,-1,0,0,-1};
int maze[110][110],vis[110][110][25];
int n,m,k;
int bfs()
{
int i,xx,yy;
queue<node> q;
memset(vis,0,sizeof(vis));
node now,no;
now.x=0; now.y=0;
now.member=1;
now.countt=0;
q.push(now);
vis[0][0][0]=1;
while(!q.empty()){
no=q.front();
q.pop();
if(no.x==n-1&&no.y==m-1)
return no.member-1;
for(i=0;i<4;i++){
now.x=no.x+ter[i][0];
now.y=no.y+ter[i][1];
if(now.x>=0 && now.x<n &&now.y>=0 &&now.y<m){
if(maze[now.x][now.y]==1)
now.countt=no.countt+1;
else
now.countt=0;
if(now.countt<=k&&vis[now.x][now.y][now.countt]==0)
{ now.member=no.member+1;
q.push(now);
}
vis[now.x][now.y][now.countt]=1;
}
}
}
return -1;
}
int main()
{ int f,i,j;
scanf("%d",&f);
while(f--){
scanf("%d %d %d",&n,&m,&k);
for(i=0;i<n;i++){
for(j=0;j<m;j++){
scanf("%d",&maze[i][j]);
}
}
printf("%d\n",bfs());
}
return 0;
}
做题要细致。。。。