• 搜索之(DFS,BFS)01


      关于他们的思想,这里就不再罗嗦了,直接 show you my code ,看题讨论 。

    题目1: 5×5迷宫 + 保存路径

    定义一个二维数组:
    int maze[5][5] = {

    0, 1, 0, 0, 0,
    
    0, 1, 0, 1, 0,
    
    0, 0, 0, 0, 0,
    
    0, 1, 1, 1, 0,
    
    0, 0, 0, 1, 0,
    

    };

    它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,
    只能横着走或竖着走,不能斜着走,
    要求编程序找出从左上角到右下角的最短路线。
    Input
    一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
    Output
    左上角到右下角的最短路径,格式如样例所示。
    Sample Input
    0 1 0 0 0
    0 1 0 1 0
    0 0 0 0 0
    0 1 1 1 0
    0 0 0 1 0
    Sample Output
    (0, 0)
    (1, 0)
    (2, 0)
    (2, 1)
    (2, 2)
    (2, 3)
    (2, 4)
    (3, 4)
    (4, 4)

    解题思路:一看到是求解最短路径,直接BFS,可是怎么存储他所走过的路径呐?说实话,这可难了我老长时间。后来经过我二哥点播,得到了下面的思路。

    BFS的下一层(无论有多少个节点)存储上一层的数组下标即可,如下图。最后就可以通过数组下标找到上一个经过的节点是什么。最后可以通过递归的形式输出最短路径。

    这里写图片描述

    #include <iostream>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <stdio.h>
    /*根据广度优先搜索的话,搜索到终点时,该路径一定是最短的*/
    using namespace std;
    struct Node
    {
        int x, y, before;
        Node() = default;
        Node(int _x, int _y, int _index) : x(_x), y(_y), before(_index) {}
        bool check()
        {
            if (x < 0 || x > 4 || y < 0 || y > 4)
                return false;
            else
                return true;
        }
    } result[20];         //记录路径
    int maze[5][5] = {0}; //迷宫
    int index = 0;
    bool bfs(Node &start, Node &end)
    {
        bool visted[5][5] = {false}; //标记数组
        int dir[4][2] = {
            {0, 1},
            {1, 0},
            {0, -1},
            {-1, 0}};
        queue<Node> QQ;
        QQ.push(start);
        visted[start.x][start.y] = true;
        Node Vnow, Vnext;
        while (!QQ.empty())
        {
            Vnow = QQ.front();
            QQ.pop();
            result[index].x = Vnow.x;
            result[index].y = Vnow.y;
            result[index].before = Vnow.before;
            index++;
    
            for (int i = 0; i < 4; ++i)
            {
                Node Vnext(Vnow.x + dir[i][0], Vnow.y + dir[i][1], index - 1);// 注意这里
    
                if (Vnext.x == end.x && Vnext.y == end.y)
                {
                    result[index].x = end.x;
                    result[index].y = end.y;
                    result[index].before = index - 1;
                    return true;
                }
                if (Vnext.check() && !visted[Vnext.x][Vnext.y] && !maze[Vnext.x][Vnext.y])
                {
                    QQ.push(Vnext);
                    visted[Vnext.x][Vnext.y] = true;
                }
            }
        }
        //数据保证有唯一解
    }
    void output(Node tmp)
    {
        if (tmp.before == 0 && tmp.x == 0 && tmp.y == 0)
        {
            printf("(%d, %d)
    ", tmp.x, tmp.y);
        }
        else
        {
            output(result[tmp.before]);
            printf("(%d, %d)
    ", tmp.x, tmp.y);
        }
    }
    int main(void)
    {
        for (int i = 0; i < 5; i++)
        {
            for (int j = 0; j < 5; j++)
            {
                cin >> maze[i][j];
            }
        }
        Node start(0, 0, 0);
        Node end(4, 4, 0);
        bfs(start, end);
        output(result[index]);
    }

    题目2:B - 闪现! + 分层(输出层数)

    Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.

    • Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
    • Teleporting: FJ can move from any point X to the point 2 × X in a single minute.

    If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

    Input
    Line 1: Two space-separated integers: N and K
    Output
    Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.
    Sample Input
    5 17
    Sample Output
    4
    Hint
    The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.

    题目大意:可向前走一步,也可向后走一步,还可以( 向前走两倍的现在步数 )

    解题思路:因为我们找的还是最快的方式,所以我们还是采取BFS的策略。这个与上一道题有所不同的是“不用存储所走过的路径”,所以我们只用关注他的层数,最后将层数输出即可 。具体的可看代码。

    这里写图片描述

    //思路: 因为是找最值,所以策略是 BFS
    #include <iostream>
    #include <queue>
    #include <string.h>
    using namespace std;
    #define MAX  100001 //草,原来那么多的RuntimeError,全是因为我数组开得太大了造成的,草草草草
    int n = 0, k = 0;
    int result = 0; //存放最终结果
    bool visted[MAX] = {false};
    int BFS(int start) // 1
    {
        queue<int> QQ;
        QQ.push(start);
        visted[start] = true;
        int Vnow, Vnext;
        while (!QQ.empty())
        {
            int loop_size = QQ.size();
            for (int j = 0; j < loop_size; j++) //有多少出多少,分层处理
            {
                Vnow = QQ.front();
                QQ.pop();
                for (int i = 0; i < 3; i++)
                {
                    if (i == 0)
                        Vnext = Vnow + 1;
                    if (i == 1)
                        Vnext = Vnow - 1;
                    if (i == 2)
                        Vnext = Vnow * 2;
                    if (Vnext == k)
                        return 0;
                    if ( Vnext >= 0 && Vnext < MAX && visted[Vnext] == false ) //这里最好是先判断出没出界,然后判断访问过没有
                    {
                        QQ.push(Vnext);
                        visted[Vnext] = true;
                    }
                }
            }
            result++;
        }
    }
    int main(void)
    {
        while (cin >> n >> k)
        {
            result = 0;
            memset(visted, 0, sizeof(visted));
            if (n >= k)
            {
                cout << n - k << endl;
                continue;
            }
            BFS(n);
            cout << result + 1 << endl;
        }
        return 0;
    }
    

    题目3:C - 不规则的棋盘 + 不同行不同列

    在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
    Input
    输入含有多组测试数据。
    每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
    当为-1 -1时表示输入结束。
    随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
    Output
    对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
    Sample Input
    2 1

    .

    .#
    4 4
    …#
    ..#.
    .#..

    -1 -1
    Sample Output
    2
    1

    解题思路:DFS。这道题与八皇后问题相当,就是要让他们不同行不同列,所以可以采取:”将列进行标记,按行进行搜索“,这里需要特别注意的一点是:要正确的解决,k < n的情况,还是ACMER的那种做法,给一个全局变量,DFS要退出时,给他减一下,最后更加需要注意的是在循环结束的时候还需要往下一行DFS一下才行。(当然还是为了解决k < n 的情况啦)

    //思路: DFS + 不同行不同列
    #include <iostream>
    using namespace std;
    char map[10][10] = {0};
    int n = 0, k = 0; // n*n 的棋盘,k个棋子
    int count = 0;  // 记录方案数目
    int temp = 0;
    bool col[10] = {false}; //对列进行标记,然后按行进行搜索
    int DFS(int x)
    {
        if (temp == k)
        {
            count++;
            return 0;
        }
        if ( x >= n ) //超出界限
            return 0;
        for (int i = 0; i < n; i++) //控制列
        {
            if (map[x][i] == '#' && col[i] == false)
            {
                col[i] = true;
                temp++;
                DFS(x + 1);
                col[i] = false;
                temp--;
            }
        }
        DFS(x + 1);
        /*为了避免:
        n= 2,k=1
    
        .#  
        #.
        的情况
        */
        return 0;
    }
    int main(void)
    {
        while (cin >> n >> k)  
        {
            if (n == -1 && k == -1)
                return 0;
            for (int i = 0; i < n; i++)
                scanf("%s", map[i]);
            count = 0;
            DFS(0); //从第0行开始
            cout << count << endl;
        }
        return 0;
    }
    

    题目4:D - 二进制? + 思维

    Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no more than 100 decimal digits.
    Input
    The input file may contain multiple test cases. Each line contains a value of n (1 <= n <= 200). A line containing a zero terminates the input.
    Output
    For each value of n in the input print a line containing the corresponding value of m. The decimal representation of m must not contain more than 100 digits. If there are multiple solutions for a given value of n, any one of them is acceptable.
    Sample Input
    2
    6
    19
    0
    Sample Output
    10
    100100100100100100
    111111111111111111

    题目大意:这个可以说是我不得不写题目大意的一道题。给一个n,找到一个m 使得他只有0和1组成,且是n的倍数。

    解题思路:这个里面,因为由0和1组成的数字是不会重复的,所以就不需要标记了,从1开始将他们一个一个放入队列即可,找到能够整除n的m即可 。

    #include <iostream>
    #include <queue>
    using namespace std;
    long long n; //输入的 n
    queue<long long> QQ; //rtm,刚开始一直不过,把queue提出来一下就过了,草
    long long BFS(long long start)
    {
        QQ.push(start);
        long long Vnow;
        while (!QQ.empty())
        {
            Vnow = QQ.front();
            QQ.pop();
            if (Vnow % n == 0)
                return Vnow;
            if ((Vnow*10) % n == 0)
                return Vnow * 10;
            if ((Vnow*10+1) % n == 0)
                return Vnow * 10 + 1 ;
            QQ.push(Vnow * 10);
            QQ.push(Vnow * 10 + 1);
        }
        return 0;
    }
    int main(void)
    {
        while (cin >> n && n )
        {
            while (!QQ.empty())
            {
                QQ.pop();
            }
            cout << BFS(1) << endl;
        }
        return 0;
    }
  • 相关阅读:
    20172021年福建省普通高校分数线,招生报考及录取统计(理科)
    SUSE Linux Enterprise 15 SP1 系统安装
    常见的网络服务器软件综合比较介绍(apache、IIS、tomcat、jboss、resin、weblogic、websphere)
    车载继电器工作原理
    java线程池使用实例
    dubbo入门教程:基于dubbo实现服务之前调用
    Sentinal
    微服务之服务网关
    ElasticSearch查询(二)
    微服务之配置管理中心
  • 原文地址:https://www.cnblogs.com/Tattoo-Welkin/p/10335268.html
Copyright © 2020-2023  润新知