首页 > 其他分享 >chapter9-搜索

chapter9-搜索

时间:2024-03-13 16:33:23浏览次数:14  
标签:状态 chapter9 int visit next 搜索 myQueue

搜索是一种有目的地枚举问题的解空间中部分或全部情况,进而找到解的方法。它的定义是:

起始状态经过一系列的状态转移抵达目标状态,我们一般用搜索树(Search Tree)来表示状态转移

搜索一般包括4个部分:

  • 1、状态空间,也叫解空间;

  • 2、状态转移;

  • 3、起始状态;

  • 4、目标状态。

如何构思上面的四个部分呢,比如状态空间是什么,举个例子:
搜索举例1.jpg

搜索举例2.jpg

1.Search Trees

以寻找从点A到点E的路径问题为例,建立一颗搜索树,建好搜索树之后,还需要确定搜索策略,即先扩展树中的哪个结点,搜索策略有宽度优先搜索、深度优先搜索两种。

搜索树.jpg

2.BFS

策略:每次优先处理当前所有未处理状态中深度最浅的一个状态,即处理最浅的结点。

采用这样的搜索策略,可以发现是一层一层从左到右的扩展,也就是先扩展的先处理,符合队列先进先出特性。

2.1 Catch That Cow

题目描述:
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≤100000) on a number line and the cow is at a point K (0≤K≤100000)on the same number line. Farmer John has two modes of transportation: walking and teleporting.

Walking:Farmer John can move from any point X to the pointsX- 1 orX+ 1 in a single minute.Teleporting: Farmer John can move from any point xto the point 2X in a single minute.

输入:
Line 1: Two space-separated integers: N and K.

输出:
Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.

搜索类题目,首先写出搜索问题的4个部分:

  • 1、状态空间 (位置n, 时间t)

  • 2、状态转移 (n-1, t+1), (n+1, t+1), (2n, t+1),共3种移动方式

  • 3、起始状态 (N, 0)

  • 4、目标状态 (K, lowestTime)

然后建立一颗搜索树:
搜索树抓牛.jpg

确定搜索策略:抓到牛并且花费时间最少,BFS逐层搜索符合题目要求。同时注意到,对重复位置的状态,为了提高搜索的效率,设置visit数组,不再对它进行扩展。

抓住那只牛
//2024-03-08 搜索 Catch that cow
#include <iostream>
#include <cstdio>
#include <queue>

using namespace std;

const int MAXN = 1e5 + 10;
bool visit[MAXN];

struct Status {
    int position;
    int time;
    Status(){}
    Status(int p, int t): position(p), time(t) {}
};

int BFS(int n, int k) {
    queue<Status> myQueue;
    myQueue.push(Status(n, 0));//把搜索树的根结点压入队列
    visit[n] = true;
    while(!myQueue.empty()) { //逐层扩展状态
        Status current = myQueue.front();
        if(current.position == k) {
            return current.time;
        }
        myQueue.pop();
        for(int i = 0; i < 3; ++i) {
            Status next = current;
            if(0 == i) {
                next.position -= 1;
            } else if(1 == i) {
                next.position += 1;
            } else {
                next.position *= 2;
            }
            next.time += 1;
            if(next.position < 0 || next.position > MAXN || visit[next.position]) {
                continue;
            }
            myQueue.push(next);
            visit[next.position] = true;
        }
    }
    return -1;
}

int main()
{
    int n, k;
    while(cin >> n >> k) {
        fill(visit, visit + MAXN, false);
        printf("%d\n",BFS(n, k));
        
    }
    return 0;
}

2.2 Find The Multiple

为了缩小状态空间,提高搜索效率,我们转换思路,搜索由0、1组成的数字中,能否被给定的数n整除
首先,写出搜索的4个部分

  • 1、状态空间 0,1构成的数字number

  • 2、状体转移 (number * 10),(number * 10 + 1)

  • 3、初始状态 1

  • 4、目标状态 number % n == 0

然后建立一颗搜索树:
倍数搜索树.jpg

Find the Multiple
//2024-03-12 Find the Mutiple 自写
#include <iostream>
#include <cstdio>
#include <queue>

using namespace std;

void BFS(int n) {
    queue<long long> myQueue;
    myQueue.push(1);
    while(!myQueue.empty()) {
        long long current = myQueue.front();
        myQueue.pop();
        if(current % n == 0) {
            cout << current << endl;
            return;
        }
        myQueue.push(current * 10);
        myQueue.push(current * 10 + 1);
    }
}

int main()
{
    int n;
    while(cin >> n) {
        if(n == 0)
            break;
        BFS(n);
    }
    return 0;
}

宽度优先搜索常被用来求解最优值问题,因为其搜索到的状态总是按照其某个关键字递增。因此,一旦问题中出现最少、最短、、最优等关键字,就要考虑是否是宽度优先搜索问题。

由于深度优先搜索并没有先入先出的特点,所以搜索到需要的状态时,该状态不再像是宽度优先搜索中的状态一样,具有某种最优的特性。因此,使用深度优先搜索策略时,常常是为了知道问题是否有解

3.DFS

策略:优先处理最深的结点,可以发现先扩展的状态可能较后才处理,与栈的后入先出特性相符,但在实际操作中,往往使用递归的方式来实现DFS。

3.1 A Knight's Journey

像象棋一样,马这个棋字的行走规则是“日”字。
马走日.jpg

同样首先分析搜索问题的4个组成部分

  • 1、状态空间:当前游历到的点的坐标,以及总共走了多少格 (x, y, step)

  • 2、状态转移:一共8种 (x-1, y-2, step+1)、(x+1, y-2, step+1)...

  • 3、起始状态: (0, 0, 1) 如果存在解,一定是从A1开始搜索,使得游历的字典序最小

  • 4、目标状态: (x, y, sizeof board) 在哪点终止不确定,但格子数确定

画出搜索树:
骑士搜索树.jpg

题目要求是找到一条路径能够遍历到棋盘的每一格,相当于要求搜索树的深度height与格子数量相同,并且注意要设置visit数组,之前已经访问过的格子不能再进行扩展或计入树高。

骑士的环球旅行
//2024-03-13 骑士的旅行
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int direction[8][2] = {
    {-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-2, 1}, {2, 1}, {-1, 2}, {1, 2}
};

const int MAXN = 30; //棋盘格数+5安全冗余

bool visit[MAXN][MAXN];

bool DFS(int x, int y, int step, string answer, int p, int q) {
    if(step == p * q) {
        cout << answer << endl << endl;
        return true;
    }
    //步数没到棋盘尺寸,就要进行扩展,有8种扩展方式
    for(int i = 0; i < 8; ++i) {
        int nx = x + direction[i][0];
        int ny = y + direction[i][1];
        if(nx < 0 || nx >= p || ny < 0 || ny >= q || visit[nx][ny]) {
            continue;
        }
        visit[nx][ny] = true;
        char col = ny + 'A';
        char row = nx + '1';
        if(DFS(nx, ny, step + 1, answer + col + row, p, q)) {
            return true;
        }
        visit[nx][ny] = false; //不再访问这个状态,这个状态下的所有扩展状态均无解
    }
    return false;
}

int main()
{
    int n;
    scanf("%d", &n);
    int caseNumber = 0;
    while(n--) {
        int p, q;
        cin >> p >> q;
        memset(visit, false, sizeof(visit));
        cout << "Scenario #" << ++caseNumber << ":" << endl;
        visit[0][0] = true;
        if(DFS(0, 0, 1, "A1", p, q)) {//压入初始状态进行处理
            continue;
        } else {
            cout << "impossible" << endl << endl;
        }
    }
    return 0;
}

3.2 Square

给出若干根长度不一的木棍,问它们能否拼成一个正方形,涉及搜索树减枝,这个例子先留个坑。

首先看搜索问题的4个部分:

  • 1、状态空间: (sum, number) sum指当前已拼凑木棍的长度,第二个number,指已经拼凑成为正方形边长的个数

  • 2、状态转移: (sum + stick[i], number),有可能发现状态变异-> (0, number + 1)

  • 3、初始状态: (0, 0)

  • 4、目标状态: (0, 4)

画出搜索树,由于扩展的状态数目由木棍数目决定,所以不定:

每往下搜索一层,就多用掉一根木根,所以可以判定木棍是否用完,以及最终拼凑出的边长个数是否等于4,所以应该用DFS搜索策略
拼成正方形.jpg

因为每个木棍只能使用一次,故要一个visit数组记录是否使用过这根木棍。

留个坑,DFS啊~

标签:状态,chapter9,int,visit,next,搜索,myQueue
From: https://www.cnblogs.com/paopaotangzu/p/18064111

相关文章

  • 文生图买不起,试试用必应的bing搜索图片服务
    首先需要一个APIkey,可以在这里先登录:MicrosoftAzure然后创建资源–>搜索bingserach-->选择bingsearchv7定价层选F1,每月有1000的额度,注意勾选最后的(我确认本人已阅读并理解下面的声明。)审阅并创建后,会跳转到该资源,如果以后要查看该资源,在主页(MicrosoftAzure)可......
  • 淘宝京东1688...按关键词搜索商品数据,商品详情数据(属性详情图,价格,sku等)批量采集,请求示
    在淘宝、京东、1688等电商平台上,按关键词搜索商品数据以及批量采集商品详情数据(如属性详情图、价格、SKU等)通常涉及到使用平台的API接口。以下是一个简化的请求示例说明,以帮助您理解这个过程。请求示例,API接口接入Anzexi581.了解API接口API接口是一种允许不同软件应用程序......
  • 淘宝京东1688...商品详情数据和关键词搜索数据采集
    要采集淘宝、京东、1688等电商平台的商品详情数据和关键词搜索数据,可以采取以下几种常见的方法:请求示例,API接口接入Anzexi58使用API接口:这些电商平台通常都提供开放API接口,允许开发者调用接口获取所需的数据。例如,通过淘宝开放平台或京东开放平台提供的API接口,可以获取......
  • 2024-03-13:用go语言,给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 输
    2024-03-13:用go语言,给定一个二叉搜索树,找到该树中两个指定节点的最近公共祖先。输入:root=[6,2,8,0,4,7,9,null,null,3,5],p=2,q=8。输出:6。答案2024-03-13:来自左程云。灵捷3.5大体步骤如下:1.首先,我们需要遍历树来找到这两个节点。从根节点开始,若两个节点都比......
  • 常见网络摄像机IP搜索不到可能导致的问题及解决办法汇总
    前两天就遇到同一个问题,网络摄像机搜不到,幸好多带了一个摄像头,不然就糗大了,关于这个问题,从工地上回来就到处请教,找了一下,所以就把答案分享出来,看看能不能帮到你。导致网络摄像机IP搜索不到的原因是多样的,而网络摄像机IP搜索不到可能引发的问题也是多样的,本文将针对网络摄像机......
  • [LeetCode][LCR174] 寻找二叉搜索树中的目标节点
    题目LCR174.寻找二叉搜索树中的目标节点某公司组织架构以二叉搜索树形式记录,节点值为处于该职位的员工编号。请返回第cnt大的员工编号。示例1:输入:root=[7,3,9,1,5],cnt=27/\39/\15输出:7示例2:输......
  • 代码随想录算法训练营day21 | leetcode 530. 二叉搜索树的最小绝对差、501. 二叉搜索
    目录题目链接:530.二叉搜索树的最小绝对差-简单题目链接:501.二叉搜索树中的众数-简单题目链接:236.二叉树的最近公共祖先-中等题目链接:530.二叉搜索树的最小绝对差-简单题目描述:给你一个二叉搜索树的根节点root,返回树中任意两不同节点值之间的最小差值。差值是一个正数,......
  • Lucene轻量级搜索引擎,真的太强了!!!Solr 和 ES 都是基于它
    一、基础知识1、Lucene是什么Lucene是一个本地全文搜索引擎,Solr和ElasticSearch都是基于Lucene的封装Lucene适合那种轻量级的全文搜索,我就是服务器资源不够,如果上ES的话会很占用服务器资源,所有就选择了Lucene搜索引擎2、倒排索引原理全文搜索的原理是使用......
  • PHP使用ES搜索
    目录版本说明安装依赖封装单例模式封装ES客户端操作封装使用示例封装MySQL数据同步ES同步双写异步双写定时任务数据订阅版本说明注意自己的PHP版本和Elasticsearch版本的对应关系,选择合适的PHPElasticsearch客户端版本Elasticsearch版本PHPES客户端版本PHP版本>=......
  • POJ--3258 River Hopscotch(二分搜索/最大化最小值)
    记录10:232023-3-11http://poj.org/problem?id=3259二分法查找最大的可能解,检查x是否符合条件(当前这个位置上的值-前上一个选取位置的值>=x)注意的点:使用了[begin,end)的左闭右开区间,所以结果要begin-1,end要从L+1开始算点击查看代码intL,N,M;introcks[5......