八数码问题+路径寻找问题+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个杯 ...
随机推荐
- Kubernetes部分Volume类型介绍及yaml示例
1.EmptyDir(本地数据卷) EmptyDir类型的volume创建于pod被调度到某个宿主机上的时候,而同一个pod内的容器都能读写EmptyDir中的同一个文件.一旦这个pod离开了这个宿主 ...
- Swift大写和小写字符串
您可以通过字符串的 uppercaseString 和 lowercaseString 属性来访问一个字符串的大写/小写版本. 复制纯文本新窗口 let normal = "Could yo ...
- 2017全球互联网技术大会回顾(附PPT)
有幸遇见 GITC2017上海站,刚好遇见你! 为期两天(6.23~24)的GITC大会在上海举行,我有幸参加了24号的那场,也就是上周六,之所以今天才来回顾,是我想等PPT出来后分享给大家! 这应该 ...
- juggle dsl语法介绍及codegen浅析
juggle语法规范如下: 类型: bool -> in cpp bool int -> in cpp int64 float -> in cpp double string -&g ...
- ECMAScript 6 中的快捷语法汇总及代码示例
对于每个 JavaScript 开发人员,快捷语法都是必备技能之一,下面就集中介绍这些快捷语法. 三元运算符 传统写法 const x = 20; let answer; if (x > 10) ...
- EF查询百万级数据的性能测试
一.起因 个人还是比较喜欢EF的,毕竟不用写Sql,开发效率高,操作简单,不过总是听人说EF的性能不是很好,也看过别人做的测试,但是看了就以为真的是那样.但是实际上到底是怎么样,说实话我真的不知道. ...
- java程序员常见面试题目
答:每当程序出现异常之后,如果程序没有进行相应的处理,则程序会出现中断现象.实际上,产生了异常之后,JVM会抛出一个异常类的实例化对象,如果此时使用了try语句捕获的话,则可以进行异常的处理,否则 ...
- 仿网易新闻app下拉标签选择菜单
仿网易新闻app下拉标签选择菜单 仿网易新闻app下拉标签选择菜单,长按拖动排序,点击增删标签控件 ##示例 ##EasyTagDragView的使用 在layout布局里添加:
- Udp实现消息的发送和接收、以及图片的上传
//Udp实现消息的发送和接收 import java.io.IOException; import java.net.DatagramPacket; import java.net.Datagram ...
- python基础(2):python的变量和常量
今天看看python的变量和常量:python3 C:\test.py 首先先说一下解释器执行Python的过程: 1. 启动python解释器(内存中) 2. 将C:\test.py内容从硬盘读入内 ...