0
点赞
收藏
分享

微信扫一扫

HDU 1072Nightmare(BFS+剪枝)


题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1072

这题好不容易调试成功了(因为各种手残。。),结果提交上去是TLE。。于是自己想剪枝方法,但是没想出来。。于是睡了个觉。。醒来还是没想出来。。。而且毫无剪枝思路。。。于是找了找网上的题解,才明白是怎样剪枝的。博客原文如下:


           这题不同于其他题的地方就是于虽然也是bfs,但对于走过的路径不能标记,因为可能还要走,注意题目要求:如果可以,可以走任意多遍。这就引发了一个问题,如果不缩减搜索范围,怎么可能走得出来呢?应该说这题好就好在不是根据走过的路径来标记,而是根据前后两次踏上同一位置是bomb离explode的时间长短来标记。简言之,如果第二次踏上一个位置,那么找出路已用的时间肯定是增加了,那为啥还要走上这条路呢?唯一的追求就是bomb离爆炸的时间增大了。所以可以利用这个条件来标记了。每次在入队前检查下爆炸时间是否比上次在同一位置的大,若是,则入队;反之,入队无意义了。

            从以上的分析中可以引出另一思路,也就是只要进入位置4,那么bomb就会延时到6分钟,最大的延时时间。换句话说,下次再进入该4位置,也

 不会获得更大的延时时间了。所以,只要访问过位置4了,就可以直接标记为0位置,表明下次不可在访问。

我的代码如下:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include<algorithm>
using namespace std;
int n, m, vis[10][10], mp[10][10];
int jx[]={0,0,1,-1};
int jy[]={1,-1,0,0};
struct node
{
    int x, y, ans, z;
};
void bfs(int a, int b)
{
    int i, j;
    queue<node>q;
    node f1,f2;
    f1.x=a;
    f1.y=b;
    f1.ans=0;
    f1.z=6;
    vis[a][b]=6;
    q.push(f1);
    while(!q.empty())
    {
        f1=q.front();
        q.pop();
        //printf("%d %d %d %d\n",f1.x,f1.y,f1.ans,f1.z);
        if(mp[f1.x][f1.y]==3&&f1.z>0)
        {
            printf("%d\n",f1.ans);
            return ;
        }
        if(f1.z<=0)
            continue ;
        for(i=0;i<4;i++)
        {
            f2.x=f1.x+jx[i];
            f2.y=f1.y+jy[i];
            f2.z=f1.z-1;
            if(f2.z>0&&f2.x>=0&&f2.x<n&&f2.y>=0&&f2.y<m&&(mp[f2.x][f2.y]==1||mp[f2.x][f2.y]==3))
            {
                f2.ans=f1.ans+1;
                if(f2.z>vis[f2.x][f2.y])
                {
                    vis[f2.x][f2.y]=f2.z;
                    q.push(f2);
                }
            }
            else if(f2.z>0&&f2.x>=0&&f2.x<n&&f2.y>=0&&f2.y<m&&vis[f2.x][f2.y]!=-1&&mp[f2.x][f2.y]==4)
            {
                f2.z=6;
                vis[f2.x][f2.y]=-1;
                f2.ans=f1.ans+1;
                q.push(f2);
            }
        }
    }
    printf("-1\n");
}
int main()
{
    int t, i, j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(vis,0,sizeof(vis));
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                scanf("%d",&mp[i][j]);
            }
        }
        int x=0;
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                if(mp[i][j]==2)
                {
                    x=1;
                    bfs(i,j);
                    break;
                }
            }
            if(x)
                break;
        }
    }
    return 0;
}





举报

相关推荐

0 条评论