zoukankan      html  css  js  c++  java
  • 类似华容道一类搜索中,状态的Hash方法(转)

    标准的华容道游戏是在一个4*5的方阵中,布有一些各种形状的棋子,当然留有若干空格.你的任务是移动棋子,并把其中的一枚棋子移动到指定的位置,如以下布局,要求把上面的A棋子移动到最下方的中间(其中一个字母为一个棋子,*表示空格):
    B A A C
    B A A C
    D E E F
    G H I J
    G * * J
     
    解法就是朴素的,搜!
     
    搜索有两个难点,一个是状态转移,一个是状态判重.对于本题来说,状态转移是简单的,只用考虑与空格相邻的棋子怎么运动就行了.不过注意,不能用移动空格来状态转移,因为很多时候要多个空格同时作用.
     
    状态判重却要花点脑筋,自然是用Hash表,不过怎样去Hash?
     
    直观的想法是,把布局图进行位压缩然后变成一个数字,不过是个很大的数字,可以吓死人.再想几秒钟就会发现刚才的想法是多么地愚蠢,因为把很多棋子拉散了的状态也考虑到了,而显然这些状态是不会出现的.
     
    棋子的形状是固定的,因此可以开个数组保存每个棋子的形状.
     
    然后,思考把每一个棋子左上角的坐标保存下来,不过,每一个棋子需要两个整数来记录,也不划算.其实这样也存在大量的多余状态,如A,B棋子同时在(1,1)就不可能存在.
     
    我们来做一个实验,先把空格看作棋子,接着,你把一个布局中的棋子从上到下,从左到右地取出来,如上图为BACDEFGHIJkl,然后取一个空棋盘,按顺序把棋子添入其中,结果,得到一个一模一样的棋盘.
     
    这启发我们用放置顺序来表示一个布局,不过仍然存在不足,因为有些棋子是一样的,如B,C,G,J.可以把他们看作一种棋子,比如都是B,然后让第一个取出的是B,第二个是C...
     
    于是,如果设
    ##
    ##=A
     
    #
    #=B
     
    ##=C
     
    #=D
     
    空格=E
     
    则上图状态的Hash码是BABDCDBDDBEE
     
    而所有状态的Hash码也无非是A B B B B C D D D D E E这12个字母的不同组合而已.
     
    这时,我们可以说,状态最多只有12!/(1!*4!*1!*4!*2!)种,其实还要少一些,因为以BBBA...打头的状态是不可能存在的,要解决这个我无能为力了,大家可以一起思考.
     
    然后,用组合公式求得字符串的字典序号,或者看作一个5进制数,取模.前者的优点是无重复,后者的优点是速度快些.

  • 相关阅读:
    U-Learning服务端
    C# 向txt文件中写入
    二维码生成 Gma.QrCodeNet (目前测试支持.net4.0及以上,但vs版本2010不可以 NuGet中搜索不到程序包)
    数据显示按规格向datatable中增加空白记录
    sql server 查询出整数 (可灵活运用)
    sql server 列字段拼接 —— STUFF
    layui confirm 嵌套使用 (随笔记)
    sql server 随记 -- 月份/日期 查询
    SQL Server 数据库备份语句
    关于ScriptManager.RegisterStartupScript 摘录
  • 原文地址:https://www.cnblogs.com/steady/p/2014021.html
Copyright © 2011-2022 走看看