怎么样判断一个八数码问题有解还是无解啊?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么样判断一个八数码问题有解还是无解啊?相关的知识,希望对你有一定的参考价值。
不会连一个知道的人也没有吧.
满意的会追加分数.谢谢.
判别方法是:
以数组为一维的举例子.
将八数码的一个结点表示成一个数组a[9],空格用0表示,设临时函数p(x)定义为:x数所在位置前面的数比x小的数的个数,
其中0空格不算在之内,那设目标状态为b[9],那r=sigma(p(x)) sigma()表示取所有的x:1-8并求和,
那对于初始状态a[9],t=sigma(p(x)),如果r和t同为奇数或者同为偶数,那么该状态有解,否则无解。
考虑到四种移动方法对sigma(p(x))的影响,左移和右移是不会影响它的值的,
更不会影响奇偶性,如果是上移或者下移就会影响:
上移:一次上移会使一个元素向前跳两个数字的位置,设这两个数字为a1,a2,
不妨设a1<a2,移的这个数字设为a0,那无非只有以下三次情况:
1,a0<a1<a2,考虑它们三者的p(x)值,p(a0)不变,p(a1)++,p(a2)++,总体增加了2
2,a1<a0<a2,p(a0)--,p(a1)不变,p(a2)++,总体不变
3,a1<a2<a0,p(a0)-=2,p(a1),p(a2)不变,总体减小了2
综合起来的结论就是不会影响sigma(p(x))的奇偶性。
参考资料:http://blog.csdn.net/jxry8888/archive/2006/12/01/1424158.aspx
参考技术A 问题是不知道什么 是八数码。。。。。。八数码问题及其扩展
先来介绍一下八数码问题
游戏的棋盘被分割成3x3的区域,上面放着标记有1~8八个数字的方形棋子,剩下一个区域为空。
游戏过程中,只能移动棋子到相邻的空区域上。当小Ho将8个棋子都移动到如下图所示的位置时,游戏就结束了。
现在的问题在于如何判断初始状态能否到达目标状态?
为了方便,我们把它写成一维的字符串,用 0 代替空格
302581647-->123456780
首先我们引入逆序的概念
设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。
如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数。
求出除0之外所有数字的逆序数之和,也就是每个数字前面比它大的数字的个数的和,称为这个状态的逆序。
当空格在同一行中左右移动的时候,该状态的逆序并不会变。
当空格在不同行中上下移动的时候,该数就前移了两位或者后移了两位,这样就有三种情况,两数均比它大或小,则逆序减二或加二;两数一大一小,则逆序不变。
所以空格的操作并不会改变序列逆序的奇偶性,所以只要初始状态和目标状态逆序的奇偶性一致就有解。
目标状态逆序为 0
302581647 的逆序为 10, 所以有解!
bool check(){ int s[20]; int cnt = 0; for(int i = 0; i<3; i++){ for(int j = 0; j<3; j++){ s[3*i+j] = start.map[i][j]; if(s[3*i+j] == \'x\') continue; for(int k = 3*i+j-1; k>=0; k--){ if(s[k] == \'x\') continue; if(s[k]>s[3*i+j]) cnt++; } } } if(cnt%2) return false; return true; }
下面我们把八数码问题扩展一下,不是 3X3 的方格,而是 NXN 的方格
同理可知,
当空格在同一行中左右移动的时候,该状态的逆序并不会变。
当空格在不同行中上下移动的时候,该数就前移了N-1位或者后移了N-1位。
所以,当 N 为奇数的时候,逆序的奇偶性不会改变,所以只要初始状态和目标状态的奇偶性一致就有解。
而当N 为偶数的时候,因为每上下移动一次,逆序的奇偶性就改变一次,所以要先算出空格到它的目标位置需要的行数m,
然后判断如果初始状态的逆序数加上m与目标状态的逆序数奇偶性相同,则有解;否则无解!
也试着想过NXNXN 的三维是否有解,原理应该是差不多的(逃
以上是关于怎么样判断一个八数码问题有解还是无解啊?的主要内容,如果未能解决你的问题,请参考以下文章