传送门
题意
给出一张n*m的图
0.墙
1.可走之路
2.起始点
3.终点
4.时间重置点
问是否能到达终点
分析
我的训练专题第一题,一开始我设个vis数组记录,然后写炸,不能处理重置点根vis的关系,然后看了iaccepted这篇blog,换了一种思路,加了一个很好的剪枝,0ms过,足可显示我的搜索思想差、实现差,切记!切记!
trick
1.dfs不能保证最先到达终点的为最短距离,不能打标记
2.剪枝说明:如果当前到达该点时间少于该点剩余时间并且步数大于该点步数,则返回
代码
#include<cstdio>
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
inline int min(int x,int y){ return x<y?x:y; }
int t,n,m,a[10][10],sx,sy,time[10][10],step[10][10];
int b[4][2]={1,0,0,-1,-1,0,0,1},ans;
bool check(int x,int y)
{
if(x<1||x>n||y<1||y>m||a[x][y]==0) return 0;return 1;
}
void dfs(int x,int y,int num,int st)
{
if(check(x,y)==0) return ;
if(num<=0) return ;
if(a[x][y]==3) { ans=min(ans,st);return ; }
if(a[x][y]==4) num=6;
if(num<=time[x][y]&&step[x][y]<=st) return ;
// printf("x=%d y=%d
",x,y);
time[x][y]=num;step[x][y]=st;
R(i,0,4)
{
int xx=x+b[i][0],yy=y+b[i][1];
dfs(xx,yy,num-1,st+1);
}
}
int main()
{
for(scanf("%d",&t);t--;)
{
scanf("%d %d",&n,&m);
F(i,1,n)F(j,1,m)
{
scanf("%d",&a[i][j]);
if(a[i][j]==2) sx=i,sy=j;
step[i][j]=100;time[i][j]=0;
}
ans=100;dfs(sx,sy,6,0);
if(ans!=100) printf("%d
",ans);
else puts("-1");
}
}