zoukankan      html  css  js  c++  java
  • 八数码问题及其扩展

    先来介绍一下八数码问题

    游戏的棋盘被分割成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;  
    }  
    View Code

    下面我们把八数码问题扩展一下,不是 3X3 的方格,而是 NXN 的方格

    同理可知,

    当空格在同一行中左右移动的时候,该状态的逆序并不会变。

    当空格在不同行中上下移动的时候,该数就前移了N-1位或者后移了N-1位。

    所以,当 N 为奇数的时候,逆序的奇偶性不会改变,所以只要初始状态和目标状态的奇偶性一致就有解。

    而当N 为偶数的时候,因为每上下移动一次,逆序的奇偶性就改变一次,所以要先算出空格到它的目标位置需要的行数m,

    然后判断如果初始状态的逆序数加上m与目标状态的逆序数奇偶性相同,则有解;否则无解!

    也试着想过NXNXN 的三维是否有解,原理应该是差不多的(逃

     
     
    转载请注明出处:http://www.cnblogs.com/ygdblogs
  • 相关阅读:
    NSDateFormatter格式详细列表一览
    Core Data could not fulfill a fault
    使用Devstack部署neutron网络节点
    配置基于Devstack的嵌套KVM虚拟化
    配置基于Devstack的嵌套KVM虚拟化
    Devstack单节点环境实战配置
    Devstack单节点环境实战配置
    Openstack贡献者须知 2 — 社区工作运作 & 代码贡献流程
    Openstack贡献者须知 2 — 社区工作运作 & 代码贡献流程
    Openstack 中的消息总线 & AMQP
  • 原文地址:https://www.cnblogs.com/ygdblogs/p/5578604.html
Copyright © 2011-2022 走看看