題目鏈接: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;
}