HDU1072:Nightmare

传送门

题意

给出一张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\n",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\n",ans);
        else puts("-1");
    }
}
posted @ 2017-03-30 22:10  遗风忘语  阅读(311)  评论(0编辑  收藏  举报