#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
【POJ1198 Solitaire 】 思路+解题报告+测试数据生成器
最新推荐文章于 2022-10-14 21:36:36 发布
这篇博客详细介绍了POJ1198题目——Solitaire的解决方案,包括使用状态压缩、哈希排重和双向BFS搜索的方法。作者在实现过程中遇到了错误,如棋子移动的编号问题和哈希表中未保存深度,通过调试和优化最终解决了问题。博客还包含了测试数据生成和代码实现。
摘要由CSDN通过智能技术生成