果然退步到不行了。。这道dfs并不难,思路也大差不多,就是一直写不对。。。心情复杂.jpg
然后看了别人的写法,要注意几点:1. 一直前进到底时用while不用dfs会更方便(这个可以和之前做的ZOJ1259模拟栈的出栈操作放在一起想,如果某项操作中不会出现别的情况就直接写while而不要递归,否则就一点点来); 2.用sign标记某条路行不行得通,能走再进行后续(一直前进); 3.一个block消除之后要退回上一步前进,同时num++; 4.num>10和ans<num要优化剪枝!!否则会TLE!! 5.注意回溯,dfs之后变回来。 附上AC代码:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> pp;
#define mkp make_pair
int n,m;//行,列
int a[25][25];
pp st,en;
int ans;
int dx[6]={0,1,0,-1,0};//1234
int dy[6]={0,0,-1,0,1};
bool judge(int x,int y)//判断能否前进
{
if(x<0||y<0||x>=n||y>=m||a[x][y]==1) return false;
else return true;
}
void dfs(int x,int y,int num)
{
if(num>10||ans<num)//优化剪枝!否则会TLE!
return;
if(judge(x,y)==false) return;
for(int i=1;i<=4;i++)//4个方向
{
int xx=x+dx[i],yy=y+dy[i];
bool sign=false;//标记这条路能不能走
while(judge(xx,yy))//一直前进到底
{
sign=true;//这个方向能走
if(a[xx][yy]==3)
{
ans=min(ans,num);
return;
}
xx+=dx[i],yy+=dy[i];
}
if(xx<0||yy<0||xx>=n||yy>=m||sign==false)//false,不可少!
continue;
//block
a[xx][yy]=0;
dfs(xx-dx[i],yy-dy[i],num+1);//退回上一步
a[xx][yy]=1;//注意回溯
}
}
int main()
{
while(scanf("%d%d",&m,&n)==2)
{
if(n==0&&m==0) break;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
scanf("%d",&a[i][j]);
if(a[i][j]==2)
st.first=i,st.second=j;
if(a[i][j]==3)
en.first=i,en.second=j;
}
ans=INF;
dfs(st.first,st.second,1);
if(ans==INF||ans>10) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}