八数码问题及其扩展

先来介绍一下八数码问题

游戏的棋盘被分割成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 的三维是否有解,原理应该是差不多的(逃

时间: 2024-10-14 07:12:17

八数码问题及其扩展的相关文章

八数码的八境界 [转载]

八数码的八境界   研究经典问题,空说不好,我们拿出一个实际的题目来演绎.八数码问题在北大在线测评系统中有一个对应的题,题目描述如下: Eight Time Limit: 1000MS    Memory Limit: 65536K  Special Judge Description The 15-puzzle has been aroundfor over 100 years; even if you don't know it by that name, you've seen it. I

【转】八数码问题及A*算法

一.八数码问题八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格,与空格相邻的棋子可以移到空格中.要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤.所谓问题的一个状态就是棋子在棋盘上的一种摆法.棋子移动后,状态就会发生改变.解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态.八数码问题一般使用搜索法来解.搜索法有广度优先搜索法.深度优

八数码问题+路径寻找问题+bfs(隐式图的判重操作)

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

HDU 1043 POJ 1077 八数码问题

以下内容转载自:http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 八数码的八境界 研究经典问题,空说不好,我们拿出一个实际的题目来演绎.八数码问题在北大在线测评系统中有一个对应的题,题目描述如下: Eight Time Limit: 1000MS    Memory Limit: 65536K  Special Judge Description The 15-puzzle has been aroundfor ove

八数码

八数码问题 一.问题描述 所谓八数码问题是指:将分别标有数字1,2,3,…,8的八块正方形数码牌任意地放在一块3×3的数码盘上.放牌时要求不能重叠.于是,在3×3的数码盘上出现了一个空格.现在要求按照每次只能将与空格相邻的数码牌与空格交换的原则,将任意摆放的数码盘逐步摆成某种特殊的排列. 二.问题分析 首先,八数码问题包括一个初始状态(strat) 和 目标状态(goal),所谓解八数码问题就是在两个状态间寻找一系列可过渡状态(strat-> strat 1-> strat 2->...

八数码问题——双向广度优先搜索解决

八数码问题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移.空格右移.空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态. 搜索顺序有两种: (1)两个方向交替进行扩展 (2)每次选择节点少的那个扩展 一般来说方法(2)可以克服两端生长不平衡的现象 // eight.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<vector> #include&l

多种方法求解八数码问题

AI的实验报告,改了改发上来.希望路过的大牛不吝赐教.非常是纳闷我的ida*怎么还没有双搜快.还有发现基于不在位启示的A*和Ida*都挺慢.尤其是ida* 搜索31步的竟然要十几秒.是我写的代码有问题吗?忘路过的大牛指导啊!!!! 另外声明一下,有些东西也是看网上各路牛人的blog学来的,因为比較杂,再次无法一一列出,总之再次感谢把自己的思考的结果放到网上与大家分享的大牛们.谢谢! 八数码问题 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每一个棋子上标有1至8的某一数字,不同棋子上标

A*八数码

帮同学写的八数码,启发式搜索 创建两个表open,close,分别用的stl中的优先队列priority_queue和map,好久没写过代码了,bug调了半天 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <set> 5 #include <queue> 6 #include <algorithm> 7 #include <ve

人工智能作业homework2--------A*算法解决八数码

1.启发式搜索算法A 启发式搜索算法A,一般简称为A算法,是一种典型的启发式搜索算法.其基本思想是:定义一个评价函数f,对当前的搜索状态进行评估,找出一个最有希望的节点来扩展. 评价函数的形式如下: f(n)=g(n)+h(n) 其中n是被评价的节点. f(n).g(n)和h(n)各自表述什么含义呢?我们先来定义下面几个函数的含义,它们与f(n).g(n)和h(n)的差别是都带有一个"*"号. g*(n):表示从初始节点s到节点n的最短路径的耗散值: h*(n):表示从节点n到目标节点