回家
这道题其实就是分析几种出不去的情况,然后就是要排除(回溯到上一步)。首先,第一种情况就是可以走的地方是个障碍(0);第二种是血量没了;第三种是走出了边界 所以这样:
if(M[x][y]==0 || !now || !vis[x][y])
{
return ;
}
if(x<1 || x>n || y<1 || y>m)
return ;
这样就解决了所有不成立的情况,然后我们接下来就要选取最优情况的答案; 方法就是取小,我们把每次的答案都取小保存,然后在返回去找还有没有更简单的答案:
if(M[x][y]==3)
{
Min=min(tot , Min);
return ;
}
接下来就是要看回血的情况了 代码很简单,就是把血补满就好了; 然后就要走下一步的部分,四个方向,每次都要扣血,并且要记步,标记是否走过,我们要把走过的路都排除,因为肯定不会是最简。 这部分代码如下:
int now1=now-1;
if(M[x][y]==4)
{
now1=5;
}
vis[x][y]=0;
dfs(x+1,y,tot+1,now1);
dfs(x-1,y,tot+1,now1);
dfs(x,y+1,tot+1,now1);
dfs(x,y-1,tot+1,now1);
vis[x][y]=1;
下面就是总的代码啦!
#include<bits/stdc++.h>
using namespace std;
int M[10][10],n,m,Min = 9999999;
bool vis[10][10];
void dfs(int x,int y,int tot,int now)
{
if(M[x][y]==0 || !now || !vis[x][y])
{
return ;
}
if(x<1 || x>n || y<1 || y>m)
return ;
if(tot > Min) //前面忘记说了,因为可能会走到一个很绕的路,所以“剪枝”,把已经超过当前值的排除。
return ;
if(M[x][y]==3)
{
Min=min(tot , Min);
return ;
}
int now1=now-1;
if(M[x][y]==4)
{
now1=5;
}
vis[x][y]=0;
dfs(x+1,y,tot+1,now1);
dfs(x-1,y,tot+1,now1);
dfs(x,y+1,tot+1,now1);
dfs(x,y-1,tot+1,now1);
vis[x][y]=1;
}
int main(){
int a,b;
scanf("%d%d",&n,&m);
memset(vis,true,sizeof(vis));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&M[i][j]);
if(M[i][j]==2)//记录下起点
{
a=i;
b=j;
}
}
dfs(a,b,0,6);
if(Min==9999999)
printf("%d",-1);//这种是完全走不出去的
else
printf("%d",Min);
return 0;
}