八数码问题+路径寻找问题+bfs(隐式图的判重操作)
Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径,
而不是像回溯法那样找到一个符合某些要求的解。
八数码问题就是路径查找问题背景下的经典训练题目。
程序框架
- process() 初始化vis数组,初始化初始节点到目标节点的移动距离
- dfs()搜索到每一个节点,如果不是目标节点,对其依次扩展所有子节点,并判重,全部子节点搜索完全后,改变父节点;如果是目标节点成功返回
- 输出最少移动步数

input:
2 6 4 1 3 7 0 5 8
8 1 5 7 3 6 4 0 2
ouput:
31
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define MAXSIZE 1000000 typedef int State[9];//s的素具类型是长度为100的数组,数组元素s[i]的数据类型是State是长度为10的数组,等同于定义了一个二维数组s[100]=iArr[100][9],数组元素师int
//int iarr[100][10],arr的数据类型是长度为100的数组,数组元素师arr[i],arr[i]的数据类型是长度为10的数组,数组元素师int
State st[MAXSIZE];//状态数一定要多定义,否则一不小心就超了
State stEnd;
int iDist[MAXSIZE]; int go[][2] =
{
{-1,0},
{1,0},
{0,-1},
{0,1}
}; int iVis[362880],fact[9];//9!=362880,8!=40320,9*8!=9!共有这么多排序,然后我们寻找,我们初始化fact
void init()
{
fact[0] = 1;
for(int i = 1 ; i < 9; i++)
{
fact[i] = fact[i-1]*i;
}
} //bool isInsert(State state)
bool isInsert(int n)//去重,采用编码与解码机制,确保一个9维状态只能映射到一个数字,并且映射的数字最大值不能超过9!
{
int iCode = 0;//编码值
for(int i = 0 ; i < 9 ; i++)
{
int iCnt = 0;
for(int j = i+1; j < 9;j++)
{
if(st[n][j] < st[n][i])//统计每个排列中,后面小于前面排列的数字个数
{
iCnt++;
}
}
iCode += fact[8-i]*iCnt;
}
if(iVis[iCode])//如果已经访问过
{
return false;
}
else
{
iVis[iCode] = 1;
return true;//同时完成赋值和返回值操作
}
} int bfs()
{
int iRear = 2,iFront = 1;
init();//这里进行判重,对于树不需要判断重复。但是对于图需要判断
while(iFront < iRear)
{
State& state = st[iFront];
if(memcmp(stEnd,state,sizeof(state)) == 0)//判断是否找到的工作要放在开头
{
return iFront;
} int iZ,iX,iY;
for(int i = 0 ; i < 9; i++)//确定0所在的位置
{
if(!state[i])
{
iZ = i;
iX = iZ / 3;
iY = iZ % 3;
break;//凡是寻找类的问题,一旦找到,必须用break跳出
}
}
//生成下一步位置
int iNewZ,iNewX,iNewY;
for(int i = 0; i < 4; i++)
{
iNewX = go[i][0] + iX;
iNewY = go[i][1] + iY;
iNewZ = iNewX*3 + iNewY;//确定0的新位置
if(iNewX >= 0 && iNewX < 3 && iNewY >= 0 && iNewY < 3)//剪枝
{
State& newState = st[iRear];//这里应该从队尾提前将原来老的状态拷贝给新的状态,再将新状态中需要修改0元素的地方进行修改,需要用引用,为修改做准备
memcpy(&newState,&state,sizeof(state));
newState[iNewZ] = state[iZ];//新矩阵0元素的位置上放0元素
newState[iZ] = state[iNewZ];//新矩阵原来放0元素的位置上现在放上新生成的0元素的坐标,这里必须用原来被交换元素的值替换
iDist[iRear] = iDist[iFront] + 1;//更新移动的步数
}
if(isInsert(iRear))//修改队尾指针
{
iRear++;
}
}
iFront++;//不管是否成功,修改队头
}
return -1;
} void process()
{
//初始化队头和队尾元素
for(int i = 0 ; i < 9;i++)
{
scanf("%d",&st[1][i]);
}
for(int j = 0 ; j < 9; j++)
{
scanf("%d",&stEnd[j]);
}
iDist[1] = 0;//设置第一步移动的距离为0
memset(iVis,0,sizeof(iVis));//初始化访问内存块,就是这句话没加导致错误的
} int main(int argc,char* argv[])
{
process();
int iRes = bfs();//返回的是front的值,但不是移动次数,移动次数得用dist来计算,因为这里是宽度优先搜索,如果用front的值,那么中间尝试的节点也算了
if(iRes > 0)
{
printf("%d\n",iDist[iRes]);
}
else
{
printf("-1\n");
}
system("pause");
return 0;
}
八数码问题+路径寻找问题+bfs(隐式图的判重操作)的更多相关文章
- hdoj 1495 非常可乐【bfs隐式图】
非常可乐 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- nyoj 21--三个水杯(隐式图bfs)
三个水杯 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识 ...
- 【UVA】658 - It's not a Bug, it's a Feature!(隐式图 + 位运算)
这题直接隐式图 + 位运算暴力搜出来的,2.5s险过,不是正法,做完这题做的最大收获就是学会了一些位运算的处理方式. 1.将s中二进制第k位变成0的处理方式: s = s & (~(1 < ...
- uva658(最短路径+隐式图+状态压缩)
题目连接(vj):https://vjudge.net/problem/UVA-658 题意:补丁在修正 bug 时,有时也会引入新的 bug.假定有 n(n≤20)个潜在 bug 和 m(m≤100 ...
- UVA 658 状态压缩+隐式图+优先队列dijstla
不可多得的好题目啊,我看了别人题解才做出来的,这种题目一看就会做的实在是大神啊,而且我看别人博客都看了好久才明白...还是对状态压缩不是很熟练,理解几个位运算用了好久时间.有些题目自己看着别人的题解做 ...
- HDU 1043 Eight 【经典八数码输出路径/BFS/A*/康托展开】
本题有写法好几个写法,但主要思路是BFS: No.1 采用双向宽搜,分别从起始态和结束态进行宽搜,暴力判重.如果只进行单向会超时. No.2 采用hash进行判重,宽搜采用单向就可以AC. No.3 ...
- 由八数码问题引入。对BFS有更深考虑
12号到今天共研究八数码问题poj1077,首先用的是普通BFS,遇到很多问题,开始用一个二级指针作为结构成员,知道了二级指针与二维数值名的不同!http://write.blog.csdn.net/ ...
- 基础学习总结(八)--Intent中显示意图和隐式意图的用法
Intent(意图)主要是解决Android应用的各项组件之间的通讯.Intent负责对应用中一次操作的动作.动作涉及数据.附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组 ...
- UVa 10603 Fill (BFS && 经典模拟倒水 && 隐式图)
题意 : 有装满水的6升的杯子.空的3升杯子和1升杯子,3个杯子中都没有刻度.不使用道具情况下,是否可量出4升水呢? 你的任务是解决一般性的问题:设3个杯子的容量分别为a, b, c,最初只有第3个杯 ...
随机推荐
- 几种Android数据序列化方案
一.引言 数据的序列化在Android开发中占据着重要的地位,无论是在进程间通信.本地数据存储又或者是网络数据传输都离不开序列化的支持.而针对不同场景选择合适的序列化方案对于应用的性能有着极大的影响. ...
- Reflect(反射)
反射.反射,程序员的快乐.反射是无处不在的. 那么什么是反射:通过反射,可以在运行时获得程序或程序集中每一个类型(包括类.结构.委托.接口和枚举等)的成员和成员的信息.有了反射,即可对每一个类型了如指 ...
- 【Android Developers Training】 106. 创建并检测地理围栏
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- js的DOM操作
ID选择器:document.getElementById("").innerHTML="" class选择器:var divc= document.getEl ...
- react-router 踩坑记
react-router踩坑分享 背景 辛苦历程 JavaScript动态修改 第一次尝试 第二次尝试 第三次尝试 第四次尝试 总结步骤 其他方案 原理 History 常见的3种History Br ...
- crm管理系统
开始的时候,我们小组开始先完成各自的静态页面,并实现页面的跳转. //部门主页面 //部门添加页面 //部门修改页面 并通过AJXA发送到后台,后台通过处理方法,并返回到前端. 需要注意的是:在下拉列 ...
- DOCKER 从入门到放弃(三)
使用docker create [image-name] 创建一个容器 创建一个nginx镜像的容器,由于没有指定各项参数,容器实用默认参数,创建后并不会启动,并将容器的ID输出到终端,如果本地没有镜 ...
- python编程快速上手之第3章实践项目参考答案
1 #!/usr/bin/env python 2 # coding:utf-8 3 # write by mfyang 4 # collatz.py 5 # 从用户读入一个值,并判断这个值是不是一个 ...
- 解决window7 x64位Anaconda启动报错:AttributeError: '_NamespacePath' object has no attribute 'sort'
最近论文需要用到python做数据分析,python语法简单,但是Windows下安装第三方包恶心的要命,statsmodels用pip死活安装不上,网上查了说包相互依赖windows下的pip不能下 ...
- 优化js脚本设计,防止浏览器假死
在Web开发的时候经常会遇到浏览器不响应事件进入假死状态,甚至弹出"脚本运行时间过长"的提示框,如果出现这种情况说明你的脚本已经失控了,必须进行优化. 为什么会出现这种情况呢,我们 ...