题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1072
题意:
给一个矩阵,从2走到3,倒计时从6开始,看是否在倒计时结束前到达3,输出最小步数。
规则:1可以走,0不可以走,遇到4,计数器重置为6。
思路:这道题目看似不难,我却做了好久,用的方法是DFS记忆化搜索,刚开始做只考虑了当走过的点的时间小于当前时间时,这个点就可以重复走,Wrong了几次,后来才考虑到需要满足两个条件时,走过的点才可以重复走:1、之前走过该点的时间小于当前时间 ;2、之前走过该点的步数大于当前步数(如果该点步数小于当前步数,再重复更新它的步数也没有意义,还会影响最后的结果)。。
#include <iostream>
using namespace std;
#define N 10
int m,n,min_time;
struct Node{
int time;//记录到达该点的时间
int vlue;//记录该点的值
int step;//记录到达该点的步数
}mp[N][N];
void DFS(int x,int y,int step,int s)
{
if(x<1||y<1||x>n||y>m||s<=0||mp[x][y].vlue==0||step>=min_time)
return;
if(mp[x][y].vlue==3)
{
min_time=min(min_time,step);
return;
}
if(mp[x][y].vlue==4)
s=6;
if(mp[x][y].time>=s&&mp[x][y].step<=step)//关键代码,优化
return;
mp[x][y].time=s;//更新该点的数据
mp[x][y].step=step;
DFS(x+1,y,step+1,s-1);
DFS(x-1,y,step+1,s-1);
DFS(x,y+1,step+1,s-1);
DFS(x,y-1,step+1,s-1);
}
int main()
{
int T,x1,y1;
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>mp[i][j].vlue;
mp[i][j].time=-1;
mp[i][j].step=INT_MAX-3;
if(mp[i][j].vlue==2)
x1=i,y1=j;
}
min_time=INT_MAX;
DFS(x1,y1,0,6);
if (min_time != INT_MAX)
cout << min_time << endl;
else
cout << "-1" << endl;
}
return 0;
}