题解 P2802 【回家】
皮皮虾letusgo · · 题解
一道DFS,但是要处理的东西挺多的。
先说一下思路吧。
首先它的读入就是不同的数字,所以如果读进来的是小H的出发地或家,要进行记录,这要方便一点。
在DFS中,需要改变的元素有四个,两个是横纵坐标,还有时间和血量。
如果时间比最小值小,且到达终点,进行最小值的改变。
定义方向增量,要注意回溯(一定要变成原来坐标的数字,若直接变为1,只能得80分)
贴上AC代码:
#include <iostream>
#include <cstdio>
using namespace std;
int n,m;//矩阵大小
int a[10][10];//矩阵存储
int x1,y1,x2,y2;//起点坐标和终点坐标
int ans=1000000000;//最小值,定义最大的
int xy[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//方向增量,四个方向
void input ()//读入函数
{
cin>>n>>m;//读入矩阵大小
for (int i=0;i<n;i++){
for (int j=0;j<m;j++){
cin>>a[i][j];//读入数字
if (a[i][j]==2) {
x1=i;
y1=j;//如果为起点,记录坐标
}
if (a[i][j]==3) {
x2=i;
y2=j;//如果为终点,也记录坐标
}
}
}
return;//结束读入
}
void dfs (int x,int y,int time,int hp){//DFS核心函数
if (time>=ans || hp<=0) return;//如果没到边界时间就超过最小值,或者没血了,直接回溯
if (x==x2 && y==y2) {//若到达终点
if (time<ans) ans=time;//比时间小,存储
return;
}
int t=a[x][y];//记录原来的值
if (a[x][y]==4) hp=6;//如果捡到鼠标,血量变为6
for (int i=0;i<4;i++){
int xx=x+xy[i][0];//横坐标增加
int yy=y+xy[i][1];//纵坐标增加
if (xx>=0 && yy>=0 && xx<=n && yy<=m && a[xx][yy]!=0) {//如果没框到边界,且不为障碍物,DFS
a[x][y]=0;//记为障碍物
dfs (xx,yy,time+1,hp-1);//DFS新坐标
a[x][y]=t;//回溯(一定要为原始数字)
}
}
return;
}
int main ()
{
input ();
dfs (x1,y1,0,6)
if (ans==1000000000) cout<<-1<<endl;//如果没变,无解
else cout<<ans<<endl;//否则输出
return 0;
}
祝大家天天AC!!!