题目描述:要求一个机器人从一个m*n的矩阵的(1,1)到(m,n)的最短路。矩阵中有障碍物,机器人最多可以一次跨越k个障碍物,遇到非障碍物则障碍物数清零。
解题思路:最短路问题。核心是在结点中加状态量,在队列中添加满足条件的结点时,在原结点的基础上改变一些状态量,添加进队,直到要么走到目的地,要么无法走到目的地。
/*************************************************************************
> File Name: UVA - 1600 Patrol Robot
> Author: Mrhanic
> Created Time: 20170316
> link : https://vjudge.net/problem/UVA-1600
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct node//x,y表示坐标,step表示步数,obs表示障碍物数
{
int x_,y_,step_,obs_;
node(){}
node(int x,int y,int step,int obs):x_(x),y_(y),step_(step),obs_(obs){}
};
const int maxn=20+10;
int graph[maxn][maxn],visit[maxn][maxn][maxn];//第三维表示从某点到一二维坐标经过的障碍物数。
int m,n,k;
const int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int solve(int st_x,int st_y)
{
if(st_x==m&&st_y==n)
{
return 0;
}
visit[1][1][0]=1;//到(1,1)经过的障碍物数为0,该节点已经添加过了。
node start(1,1,0,0),temp;
queue<node> q;
q.push(start);
while(!q.empty())
{
temp=q.front();
for(int i=0;i<4;i++)
{
int cnt=temp.obs_;//当前节点的障碍物数。
int x =temp.x_ + dx[i],y =temp.y_ + dy[i];
if(x>=1&&x<=m&&y>=1&&y<=n)
{
if(x==m&&y==n) return temp.step_+1;
if(graph[x][y]==1)//障碍物加一
{
cnt++;
}
else cnt=0;//障碍物清零。
if(cnt<=k&&!visit[x][y][cnt])//还可以穿越障碍物且该节点还没添加过。
{
node now(x,y,temp.step_+1,cnt);
q.push(now);
visit[x][y][cnt]=1;
}
}
}
q.pop();
}
return -1;
}
int main()
{
int kase;
cin >> kase;
while(kase--)
{
memset(graph,0,sizeof(graph));
memset(visit,0,sizeof(visit));
cin >> m >> n >> k;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
cin >> graph[i][j];
}
}
cout << solve(1,1) << endl;
}
return 0;
}