我们在解决八数码问题是,会关心一个解空间的问题,比如我们进行了27步操作时,当前状态有多少可能的方案呢?
统计解空间的大小,有助于我们更好的优化算法。
- 我们可以利用广度优先策略,来统计第N步的可能方案。
- 利用hash表来存储可行方案,从而剔除重复方案。
- 利用回溯的方式,从第N步开始往起点回退,能回退到起点的方案就是可能性方案,记录该方案。
下面就是我们统计八数码问题进行到第27步以后,统计解空间大小的代码:
#include <iostream>
#include <set>
#include <vector>
#include <queue>
using namespace std;
//向四个方向生成新的方案
int x_axis[] = {-1, 0, 0, 1};
int y_axis[] = { 0, -1, 1, 0};
/**
*generate函数:生成新的一层解决方案
*
*@param queue<vector<int>> myqueue, set<vector<int>> myset;
*/
void generate(queue<vector<int> > &nodes, set<vector<int> > &states)
{
//拓展已经经过的所有节点
vector<int> layer;
//使用空的向量来区分不同层的树枝
nodes.push(layer);
//拓展当前层的所有节点
while(nodes.front().size() != 0)
{
vector<int> current = nodes.front();
//拓展当前节点
//寻找0的位置
int px;
int py;
for(int i = 0; i < 9; ++i)
{
if(current[i] == 0)
{
px = i / 3;
py = i % 3;
}
}
//想四个方向拓展,首先得判断能否拓展
for(int i = 0; i < 4; i++)
{
if(px+x_axis[i] >= 0 && px+x_axis[i] < 3 &&
py+y_axis[i] >= 0 && py+y_axis[i] < 3)
{
vector<int> fresh = current;
fresh[px*3+py] = fresh[(px+x_axis[i])*3+(py+y_axis[i])];
fresh[(px+x_axis[i])*3+(py+y_axis[i])] = 0;
//在哈希表中寻找新生成的节点是否已经出现过,如果出现过就抛弃。
if(states.find(fresh) == states.end())
{
states.insert(fresh);
nodes.push(fresh);
}
}
}
//将已经遍历的点推出队列
nodes.pop();
}
//将队列中标识分层的空向量删除掉
nodes.pop();
//清空哈希表
//states.clear();
cout<<nodes.size()<<endl;
return;
}
int main(int argc, char *argv[])
{
//构造目标状态的数据
vector<int> goal;
for(int i = 0; i < 9; ++i)
{
goal.push_back(i);
}
//给定循环的次数
int times = 27;
//初始化队列和哈希表
queue<vector<int> > nodes;
set<vector<int> > states;
nodes.push(goal);
states.insert(goal);
while(times--)
{
generate(nodes, states);
}
//输出哈希表的大小
cout<<"搜索空间大小为:"<<nodes.size()<<endl;
return 0;
}