人工智能笔记01 一般图搜索——基于《人工智能》 朱福喜,清华大学出版社,2016

什么是搜索?

搜索算法是利用计算机的高性能来有目的的穷举一个问题解
空间的部分或者所有的可能情况,从而求出问题的解的一种
计算机算法

搜索算法分类

Ø 一般图搜索
Ø 启发式搜索
Ø 不确定性搜索
Ø 博弈搜索
Ø 约束满足

图搜索的基本概念

图搜索是搜索过程可以用图结构的形式呈现的一类搜索算法。图可以更加形象与清晰地描述搜索过程。

• 在计算机科学中,一个图就是一些顶点的集合,这些顶点通过一系列边连接。顶点用圆圈表示,边就是这些圆圈之间的连线,顶点之间通过边连接。

节点深度
根节点 = 0
其他根节点 = 父 + 1

路径
设一节点序列为 ( n 0 , n 1 , … , n k ) (n_0, n_1,…,n_k) (n0,n1,,nk),对于 i = 1 , … , k i=1,…,k i=1,,k,若节点ni-1具有一个后继节点 n i n_i ni,则该序列称为从 n 0 n_0 n0 n k n_k nk的路径。

路径耗散
一条路径的耗散值等于连接这条路径各节点间所有耗散值的总和。用C(ni, nj)表示从ni到nj的路径的耗散值。

C ( n 1 , n 4 ) = C ( n 1 , n 2 ) + C ( n 2 , n 3 ) + C ( n 3 , n 4 ) C(n_1,n_4)=C(n_1,n_2)+C(n_2,n_3)+C(n_3,n_4) C(n1,n4)=C(n1,n2)+C(n2,n3)+C(n3,n4)

扩展结点
生成出该节点的所有后继节点,并给出它们之间的耗散值。这一过程称为“扩展一个节点”。

• 问题状态
Ø 问题求解过程中的一种状态,某种中间过程的一个呈现,其对应于某个图G。
• 初始状态
Ø 问题求解之前的状态,一般是一个空状态,用符号S表示,也用作表示初始节点。
• 目标状态
Ø 包含求解目标的一种状态,用符号T表示,也用作表示一个目标节点。(T到S的反推代表一个解)
• 状态空间
Ø 问题求解过程中所有可能状态的集合

Ø 从给定的初始状态出发
Ø 一步一步选择节点扩展,得到新的状态
Ø 重复上述步骤,直到扩展目标状态(T到S的路径即为所求解),或者无
节点可扩展(该问题无解

Open表存储还未扩展的节点
Closed表存储已经扩展过的节点
状态图G当前已经扩展出来节点构成的当前状态

算法框架

1 G=G0 (G0=s), Open:=(s), Closed:=( ); // 初始化
2 Loop: If Open=( ) Then Exit(Fail); // 失败停止
3 n:=First(Open), Remove(n, Open), Add(n, Closed); // 更新数据结构
4 If Goal(n),Then Exit(Success); // 成功停止
5 Expand(n){mi}, 计算耗散值, G:=Add(mi, G); // 扩展节点,更新状态
6 标记和修改指针: // 修改指针(最优解)
Add(mj, Open), 并标记mj到n的指针;
计算是否要修改mk、ml到n的指针;
计算是否要修改ml到其后继节点的指针;
7 对Open中的节点按某种原则重新排序; // 保证找到最优解
8 Go Loop;

图搜索例子:八数码题

在这里插入图片描述

在这里插入图片描述

思路

BFS比较简单
DFS应该也可以,可能得涉及到迭代加深的内容

代码

#include<iostream>
#include<bits/stdc++.h>

using namespace std;

char direction[] = {'u', 'd', 'l', 'r'};
int flag = 0;
string ROAD = "unsolvable";

struct A
{
    string road = "";
    int mark = 0;
};


int bfs(string& aim, queue<string>& q, map<string,A>& visit)
{
    while(!q.empty())
    {

        string last_now = q.front();
        if(aim == last_now)//满足aim的地图了
        {
            ROAD = visit[last_now].road;
            return 1;
            //表明已经完成探路
        }
        // cout << last_now << endl;
        // cout << visit[last_now].road << endl << endl;

        q.pop();

        int x_location = last_now.find('x');
        int x_row = x_location / 3;
        int x_col = x_location % 3;
        string last_road = visit[last_now].road;    

        for(int i = 0; i < 4; i++)
        {
            //每次往不同的方向都要重新初始化
            string now = last_now;//初始化现在的地图
            string road = last_road;//初始化现在的路径
            //cout << x_row << " " << x_col << endl;
            if(direction[i] == 'u')
            {
                if(x_row == 0)
                    continue;
                else
                {
                    int temp = now.find('x');
                    now[temp] = now[temp - 3];
                    now[temp - 3] = 'x';
                    road += 'u';
                }
            }
            else if(direction[i] == 'd')
            {
                if(x_row == 2)
                    continue;
                else
                {
                    int temp = now.find('x');
                    now[temp] = now[temp + 3];
                    now[temp + 3] = 'x';
                    road += 'd';
                }
            }
            else if(direction[i] == 'l')
            {
                if(x_col == 0)
                    continue;
                else
                {
                    int temp = now.find('x');
                    now[temp] = now[temp - 1];
                    now[temp - 1] = 'x';
                    road += 'l';
                }
            }
            else if(direction[i] == 'r')
            {
                if(x_col == 2)
                    continue;
                else
                {
                    int temp = now.find('x');
                    now[temp] = now[temp + 1];
                    now[temp + 1] = 'x';
                    road +='r';
                }
            }   
        
            if(visit[now].mark == 1)
            {
                continue;
            }
            else
            {
                visit[now].road = road;
                visit[now].mark = 1;
                q.push(now);
            }
        }    
        
    }
        
        
    return 0;
}

int main()
{
    string aim = "12345678x";
    string now;
    cin >> now;
    string road = "";

    queue<string>q;
    map<string, A> visit;//用于记录是否访问过这个状态
    //第一个string放记录的地图 第二个放对应的路径road
    
    visit[now].road = road;
    visit[now].mark =  1;
    q.push(now);

    bfs(aim, q, visit);
    cout << ROAD << endl;

    return 0;
}

小结

• 一般图搜索的基本要素

Ø 初始状态
Ø 目标状态
Ø 扩展规则(后继函数)
Ø 耗散函数及排序规则

• 一般图搜索是一类无信息搜索

Ø 与所求解问题无关
Ø 深度优先搜索
Ø 宽度优先搜索

• 一般图搜索算法是很多算法的基础

Ø 通常通过在搜索前,根据条件降低搜索规模
Ø 根据问题的约束条件进行剪枝
Ø 利用搜索过程中的中间解,避免重复计算
Ø 利用问题启发式信息,减少搜索空间

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值