hduoj 1253 胜利大逃亡 和 nyoj 523 亡命逃亡 【搜索】

36 篇文章 0 订阅
13 篇文章 0 订阅

链接:

hduoj 1253:http://acm.hdu.edu.cn/showproblem.php?pid=125

nyoj  523:http://acm.nyist.net/JudgeOnline/problem.php?pid=523

在杭电上看不懂题的可以到nyoj看看,简单说一下题意,定义一个数组map [ 60] [60 ] [60 ] ,如果存放输入数据不是从数组的下标0 开始,3个地方都是从下标 1 开始。就是求map [ 1 ][ 1 ][ 1 ] 到 map [ A ] [ B ][ C ] 的最短时间。题目中要求是0为路,1为墙。。每次可以向相邻的 6 个方位走,如果可以到达目的地,求出最短时间。。然后在和T比较,然后........就不用我说了吧。。

说说我的思路吧:广度优先搜索,搜索过程中,搜过的点标记,下次遇到不再搜索,每组输入数据都初始化map数组为0,存放输入数据是从下标1开始,题目中0为路,1为墙,我们改为1为路,0为墙。。为什么这样呢?狠简单,这样相当于在输入数据边上加上一层0,即一层墙。。这样你就不用担心越界的问题了,而且这样做,不需要剪枝在hduoj  nyoj  就能ac。。(后台数据比较弱。nyoj现在正在修改后台数据,就是卡我的那个没剪枝的代码,O(∩_∩)O哈哈~),但是不这样做,你若没剪枝你可能就会超时。。

再说一下怎么剪枝,想一想:

(1)如果 目的地 map[ A ]  [ B ] [ C ]是墙,你就根本到不了,所以直接输出-1,不用再搜索了。。

(2)如果 都是路,木有墙,最短时间为A+B+C,木有错吧,如果此时最短时间>T,直接输出-1,没必要搜索了。。

具体思路就这些了,有问题或者更好思路的欢迎讨论交流,哈哈。。

贴一下代码:

 
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int kj[]={0,0,0,0,1,-1},sx[]={0,0,1,-1,0,0},zy[]={1,-1,0,0,0,0};
int map[60][60][60],ac[60][60][60];
int n,m,w,t;
struct hello
{
    int x,y,z,step;
};
void bfs()
{
    int a,b,x,y,z,sum,loop=0;
    queue<hello>Q;
    hello ok1={1,1,1,0};
    Q.push(ok1);
    ac[1][1][1]=1;
    while(!Q.empty())
    {
        x=Q.front().x;
        y=Q.front().y;
        z=Q.front().z;
        sum=Q.front().step;
        Q.pop();
        if(x==w&&y==n&&z==m)
            {loop=1;break;}
        for(a=0;a<6;a++)  //向相邻6个方向搜索
        {
            int i=x+kj[a];
            int j=y+sx[a];
            int p=z+zy[a];
            if(ac[i][j][p]==0&&map[i][j][p]==1)
            {
                hello ok2={i,j,p,sum+1};
                Q.push(ok2);
                ac[i][j][p]=1;
            }
        }


    }
    if(sum<=t&&loop==1)
       printf("%d\n",sum);
    else
       printf("-1\n");


}
int main()
{
    int a,b,c,k,kkk;
    scanf("%d",&k);
    while(k--)
    {
        memset(ac,0,sizeof(ac));//用来标记该点是否走过
        memset(map,0,sizeof(map));
        scanf("%d %d %d %d",&w,&n,&m,&t);
        for(c=1;c<=w;c++)
          for(a=1;a<=n;a++)
            for(b=1;b<=m;b++)
                 {
                     scanf("%d",&kkk);
                     if(kkk==0)      //转换
                        map[c][a][b]=1;
                     else
                        map[c][a][b]=0;
                 }
       if(map[w][n][m]==0||w+n+m>t)//剪枝。。
         {printf("-1\n");continue;}
        bfs();
    }
}
        


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值