【POJ1198 Solitaire 】 思路+解题报告+测试数据生成器

这篇博客详细介绍了POJ1198题目——Solitaire的解决方案,包括使用状态压缩、哈希排重和双向BFS搜索的方法。作者在实现过程中遇到了错误,如棋子移动的编号问题和哈希表中未保存深度,通过调试和优化最终解决了问题。博客还包含了测试数据生成和代码实现。
摘要由CSDN通过智能技术生成
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
//#define DBG
//#define INPUT
//#define DBG1
using namespace std;

/**
        Problem: poj1198 - Solitaire
        Begin Time : 18:33 15th/Mar/2012
        End Time:   2:40 a.m. 16th/Mar/2012
        Test Data:
        见数据生成器代码
        Standard Output:
        用本程序对拼即可
        Thought:
          这个代码写的太垃圾了,比较崩溃。
          ①:状态压缩:
            棋盘上只有四个棋子,一行数字(x1 y1 x2 y2 x3 y3 x4 y4)
            代表了四个棋子在棋盘上的位置。
            我们把各个棋子按照x的大小进行排序。
            然后把其变成一个八位数来表示当前的棋盘状态
          ②:HASH排重 (*)
            把待搜索的棋盘状态插入自己的hash表中。
            注意,由于DFS是双向的,hash表要维护两个,一个是正向搜索的hash表
            一个是反向搜索的hash表。如果其的key发生冲突并且内容相同,那么插入失败。
          ③:状态搜索:
            每次从两个队列(一个表示从开始状态,一个表示从结束状态)搜索中取出表示该次搜索
            应该搜索的状态,然后将搜索的内容在不同的hash表里进行检索,例如:
            从begin_queue[front]取出的bval1(表示从开始状态搜索到的某个中间状态)
            应该在end_hash中检索,如果在end_hash中找到了该状态,并且该状态对应的
            end_deep(从结束状态到这个中间状态经过的步数)与当前状态的deep加起来小于等于8
            那么就代表找到了,标志isFound = true;然后输出
          ④:如何搜索
            搜索的时候还是四个向量,左右上下,只不过进行左右上下搜索的时候记得判断一下周围是否有棋子
            这个做法是把压缩过的状态还原成int tmp[8],然后找移动后的棋子tmp[i],tmp[i+1]在其他的tmp中有
            没有相同的,2*i是x,2*i+1是y
            如果tmp[2*i] == tmp[2*j] && tmp[2*i + 1] == tmp[2*j + 1]的话,就代表i移动后与j重叠。
            按照“跳过子”的规则进行移动。

        Knowledge:
          HASH排重+状态压缩+双向BFS搜索
        The Experience:
            WA点1 : 在进行棋子的移动的时候,switch(dir) case 0 1 2 3写成了 1 2 3 4,不应该犯!
            WA点2:非常脑残的在hash表中每个状态没有保存对应的深度!所以有时候从beginState搜索到beginDeep = 3
                    的时候,在endHash表中找到了一个endDeep = 6 的状态与之对应,由于没有保存endHash中每个状态的深度
                    所以这时候输出了,WA了4次(貌似)
*/
const int HASHKEY = 100003;
const int HASHEND = 2;
const int HASHBEGIN = 1;
const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,-1,1};
int bs[8];  ///开始状态
int es[8];  ///结束状态
int bhash[200000];
int bnext[200000];
i
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值