• pku 3009 Curling 2.0


    非常好的一道搜索题,花了一个下午和一个晚上去做去理解

    题意:虽然英语很长,不过不是太难懂,就是可以向四个方向扔小球,每次扔出去,会一直走,直到遇到墙时停止,或出界失败,而遇到墙后,球会停止,然后所撞到的墙消失,给一个起点和一个终点,能在10步之内到达的则输出其最少步数

    思路:虽然是搜dfs题目搜到的这道题,但是开始看题意是说要求最少的步数,第一个想到的自然是BFS,感觉稍微变形下,类似回溯,只是每次都是四个方向同时判断,然后入队,再继续广搜。然而,花了整整2个多小时,依然调不好,思路也越来越乱了,上百度搜了下,全是dfs的解法。仔细看了下,发现和自己写的bfs几乎一致,于是,决定从新再写一遍,改一改回溯,希望能更短时间内完成,而且图不大,空间换时间还是值得的。当然,更主要的原因是,不知道没理解为什么最少步数却没人用bfs呢……

    但当我正真再次改的时候,突然发现了问题所在,因为bfs是同时想各个方向的,而每次如果撞到一面墙A,而另一方向搜的时候,这个被撞的墙A还是存在的,所以要做bfs理论上也是可以的,只是每次向外搜索一次,每个方向都应该增加一个20*20的数组,这个空间是否开的起真是一个问题……而且即使开的起,也是极不划算的,因为题目只要在10次之内,所以dfs也不会浪费太多时间

    以下是代码,改自网上一个代码(ps:他的代码当时还开了一个宽搜用的结构体数组,没有删掉,呵呵,看来不止我一个人遇到这个问题)

    code:

    #include <iostream>
    #include <cstdio>
    using namespace std;
    const int N = 25;
    int sqr[N][N], w , h;
    int dir[4][2] = {{1 , 0} , {-1 , 0} , {0 , -1} , {0 , 1}};
    int ret ;

    void DFS(int a , int b , int step)
    {
        if(step > 10 || step > ret) return;
        for(int i=0; i < 4; i++)
        {
            int at = a + dir[i][0];
            int bt = b + dir[i][1];
            if(at <= 0 || bt <= 0 || at > h || bt > w)
                continue;
            if(sqr[at][bt] == 1) continue;
            int flag = 0;
            int tx = a , ty = b;
            while(sqr[at][bt] != 1)
            {
                tx = at, ty = bt;
                if(sqr[at][bt] == 3 && step + 1 <= 10)
                {
                    ret = min(ret , step + 1);
                }
                at += dir[i][0];
                bt += + dir[i][1];
                if(at <= 0 || bt <= 0 || at > h || bt > w)
                {
                    flag = 1;
                    break;
                }
            }
            if(flag) continue;
            sqr[at][bt] = 0;
            DFS(tx , ty , step + 1);
            sqr[at][bt] = 1;
        }
    }

    int main()
    {
        //freopen("in.txt" , "r" , stdin);
        while(scanf("%d %d" , &w , &h), w && h)
        {
            int sx ,sy;
            ret = 20;
            for(int i=1; i <= h; i++)
                for(int j=1; j <= w; j++)
                {
                    scanf("%d" , &sqr[i][j]);
                    if(sqr[i][j] == 2)
                    {
                        sx = i;
                        sy = j;
                    }
                }
            DFS(sx , sy , 0);
            printf("%d\n" , ret == 20 ? -1 : ret);
        }
        return 0;
    }

  • 相关阅读:
    C++ istringstream总结
    C++各数据类型的最值
    AcWing 机器人跳跃问题 二分
    蓝桥杯 矩形面积交
    蓝桥杯 完美的代价
    蓝桥杯 数的读法
    国内 镜像 下载
    redis的pipline使用
    MySQL额外操作
    sql强化演练( goods 表练习)
  • 原文地址:https://www.cnblogs.com/FreeAquar/p/2029897.html
Copyright © 2020-2023  润新知