题目大意:给一个m*n(1<=m,n<=20)的0-1图(0空地,1障碍)
不能连续穿越k(0<=k<=20)次障碍
求从左上到右下最短路径
解题思路:图的遍历dfs
从四个方向遍历直到最后
若到最后则判断是否最小
注意事项:穿越障碍的处理
给最短路赋大值,若未改变输出-1
// TLE
#include <cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int p,q,k;
int n[22][22];
bool v[22][22]; //访问标记
int f; //最短路径
int z[][2]={ {-1,0},{0,1},{1,0},{0,-1} } ; //4个坐标
void dfs(int x,int y,int t,int zk)
{
v[x][y]=1;
if(x==p-1&&y==q-1)
{
if(t<f)
f=t;
return;
}
else
{
int nx,ny;
for(int i=0;i<4;++i)
{
nx=x+z[i][0];
ny=y+z[i][1];
if(nx>=0&&nx<p&&ny>=0&&ny<q&&v[nx][ny]==0)
{
if(n[nx][ny]==0)
{
dfs(nx,ny,t+1,0);
v[nx][ny]=0;
}
else if(zk<k)
{
dfs(nx,ny,t+1,zk+1);
v[nx][ny]=0;
}
}
}
}
}
int main()
{
int qq;
cin>>qq;
for(int i=0;i<qq;++i)
{
cin>>p>>q>>k;
memset(v,0,sizeof(v));
f=p*q;
for(int i=0;i<p;++i)
for(int j=0;j<q;++j)
scanf("%d",&n[i][j]);
dfs(0,0,0,0);
if(f<p*q)
{
cout<<f<<endl;
}
else
{
cout<<-1<<endl;
}
}
return 0;
}
改了一下,访问数组v[x][y][c]表示走到x,y的时候 穿过了c个墙,时的步数
#include <cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int p,q,k;
int n[22][22];
int v[22][22][22]; //访问标记
int f; //最短路径
int z[][2]={ {-1,0},{0,1},{1,0},{0,-1} } ; //4个坐标
void dfs(int x,int y,int t,int zk)
{
if(x==p-1&&y==q-1)
{
if(t<f)
f=t;
return;
}
else
{
int nx,ny;
for(int i=0;i<4;++i)
{
nx=x+z[i][0];
ny=y+z[i][1];
int c=zk;
if(n[nx][ny]==0)
{
c=0;
}
else
{
c++;
}
if (nx >= 0 && nx < p && ny >= 0 && ny < q)
{
if ((v[nx][ny][c] < 0 ||
v[nx][ny][c] > t+1) && c <= k)
{
v[nx][ny][c] = t + 1;
dfs(nx, ny, t + 1, c);
}
}
}
}
}
int main()
{
int qq;
cin>>qq;
for(int i=0;i<qq;++i)
{
cin>>p>>q>>k;
memset(v,-1,sizeof(v));
f=1<<30;
for(int i=0;i<p;++i)
for(int j=0;j<q;++j)
cin>>n[i][j];
dfs(0,0,0,0);
if(f!=(1<<30))
{
cout<<f<<endl;
}
else
{
cout<<-1<<endl;
}
}
return 0;
}