什么是搜索?
搜索算法是利用计算机的高性能来有目的的穷举一个问题解
空间的部分或者所有的可能情况,从而求出问题的解的一种
计算机算法
搜索算法分类
Ø 一般图搜索
Ø 启发式搜索
Ø 不确定性搜索
Ø 博弈搜索
Ø 约束满足
图搜索的基本概念
图搜索是搜索过程可以用图结构的形式呈现的一类搜索算法。图可以更加形象与清晰地描述搜索过程。
• 在计算机科学中,一个图就是一些顶点的集合,这些顶点通过一系列边连接。顶点用圆圈表示,边就是这些圆圈之间的连线,顶点之间通过边连接。
节点深度
根节点 = 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;
}
小结
• 一般图搜索的基本要素
Ø 初始状态
Ø 目标状态
Ø 扩展规则(后继函数)
Ø 耗散函数及排序规则
• 一般图搜索是一类无信息搜索
Ø 与所求解问题无关
Ø 深度优先搜索
Ø 宽度优先搜索
• 一般图搜索算法是很多算法的基础
Ø 通常通过在搜索前,根据条件降低搜索规模
Ø 根据问题的约束条件进行剪枝
Ø 利用搜索过程中的中间解,避免重复计算
Ø 利用问题启发式信息,减少搜索空间