POJ-3131-Cubic Eight-Puzzle(双向BFS+哈希)
Description
Let’s play a puzzle using eight cubes placed on a 3 × 3 board leaving one empty square.
Faces of cubes are painted with three colors. As a puzzle step, you can roll one of the cubes to a adjacent empty square. Your goal is to make the specified color pattern visible from above by a number of such steps.
The rules of this puzzle are as follows.
Coloring of Cubes: All the cubes area colored in the same way as shown in Figure 1. The opposite faces have the same color.

Figure 1: Coloring of a cube
Initial Board State: Eight cubes are placed on the 3 × 3 board leaving one empty square. All the cubes have the same orientation as shown in Figure 2. As shown in the figure, squares on the board are given x and y coordinates,
(1, 1), (1, 2), …, and (3, 3). The position of the initially empty square may vary.
Figure 2: Initial board state
Rolling Cubes: At each step, we can choose one of the cubes adjacent to the empty square and roll it into the empty square, leaving the original position empty. Figure 3 shows an example.

Figure 3: Rolling a cube
Goal: The goal of this puzzle is to arrange the cubes so that their top faces form the specified color pattern by a number of cube rolling steps described above.
Your task is to write a program that finds the minimum number of steps required to make the specified color pattern from the given initial state.
Input
The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated by a space. The number of datasets is less than 16. Each dataset is formatted as follows.
x y F11 F21 F31 F12 F22 F32 F13 F23 F33
The first line contains two integers x and y separated by a space, indicating the position (x, y) of the initially empty square. The values of x and y are 1, 2, or 3.
The following three lines specify the color pattern to make. Each line contains three characters F1j, F2j, and F3j, separated by a space. Character Fij indicates
the top color of the cube, if any, at the position (i, j) as follows:
B:Blue,
W:White,
R:Red,
E:the square is Empty.
There is exactly one ‘E’ character in each dataset.
Output
For each dataset, output the minimum number of steps to achieve the goal, when the goal can be reached within 30 steps. Otherwise, output “-1” for the dataset.
Sample Input
1 2
W W W
E W W
W W W
2 1
R B W
R W W
E W W
3 3
W B W
B R E
R B R
3 3
B W R
B W R
B E R
2 1
B B B
B R B
B R E
1 1
R R R
W W W
R R E
2 1
R R R
B W B
R R E
3 2
R R R
W E W
R R R
0 0
Sample Output
0
3
13
23
29
30
-1
-1
Source
思路:数据太大,先抽象出状态,再哈希一下,然后就是双向BFS。
#include <stdio.h>
#include <string.h>
#include <stack>
using namespace std;
#define INF 99999999
struct{
int step,state;
}t,que1[1000000],que2[1000000];
stack<int>stk;
bool vis1[5000007],vis2[5000007];
int top1,top2,bottom1,bottom2,mp[9],nxt[2][7]={{0,4,6,5,1,3,2},{0,5,3,2,6,1,4}},head[5000007],next[5000007],val[5000007],total;
int hashval(int x)
{
int t,i;
t=x%5000007;
for(i=head[t];i!=-1;i=next[i])
{
if(val[i]==x) return i;
}
val[total]=x;
next[total]=head[t];
head[t]=total;
total++;
return total-1;
}
void pushtarget(int cnt,int state)
{
if(cnt==-1)
{
vis2[hashval(state)]=1;
que2[bottom2].step=0;
que2[bottom2].state=state;
bottom2++;
return;
}
if(mp[cnt]%2)
{
pushtarget(cnt-1,state*7+mp[cnt]);
pushtarget(cnt-1,state*7+mp[cnt]+1);
}
else pushtarget(cnt-1,state*7);
}
int getstate()
{
int temp=0;
for(int i=8;i>=0;i--)
{
temp=temp*7+mp[i];
}
return temp;
}
void spread(int x)
{
int i=0,temp,cnt,old;
while(i<9)
{
if(x%7==0) cnt=i;
mp[i++]=x%7;
x/=7;
}
cnt+=1;
if(cnt>=0 && cnt<9 && cnt%3>0)
{
old=mp[cnt];
mp[cnt-1]=nxt[0][mp[cnt]];
mp[cnt]=0;
stk.push(getstate());
mp[cnt]=old;
mp[cnt-1]=0;
}
cnt-=1;
cnt-=1;
if(cnt>=0 && cnt<9 && cnt%3<2)
{
old=mp[cnt];
mp[cnt+1]=nxt[0][mp[cnt]];
mp[cnt]=0;
stk.push(getstate());
mp[cnt]=old;
mp[cnt+1]=0;
}
cnt+=1;
cnt-=3;
if(cnt>=0 && cnt<9)
{
old=mp[cnt];
mp[cnt+3]=nxt[1][mp[cnt]];
mp[cnt]=0;
stk.push(getstate());
mp[cnt]=old;
mp[cnt+3]=0;
}
cnt+=3;
cnt+=3;
if(cnt>=0 && cnt<9)
{
old=mp[cnt];
mp[cnt-3]=nxt[1][mp[cnt]];
mp[cnt]=0;
stk.push(getstate());
mp[cnt]=old;
mp[cnt-3]=0;
}
cnt-=3;
}
int bfs()
{
int step1=0,step2=0,ans=INF,temp;
for(step1=0;step1<=20;step1++)
{
while(top1<bottom1 && que1[top1].step==step1)
{
spread(que1[top1].state);
while(!stk.empty())
{
temp=stk.top();
stk.pop();
if(vis2[hashval(temp)])
{
return step1+step2+1;
}
if(!vis1[hashval(temp)])
{
vis1[hashval(temp)]=1;
que1[bottom1].state=temp;
que1[bottom1].step=que1[top1].step+1;
bottom1++;
}
}
top1++;
}
while(top2<bottom2 && que2[top2].step==step2 && step2<9)
{
spread(que2[top2].state);
while(!stk.empty())
{
temp=stk.top();
stk.pop();
if(vis1[hashval(temp)]) return step1+step2+2;
if(!vis2[hashval(temp)])
{
vis2[hashval(temp)]=1;
que2[bottom2].state=temp;
que2[bottom2].step=step2+1;
bottom2++;
}
}
top2++;
}
if(step2<9) step2++;
}
return -1;
}
int main()
{
int x,y,i,j,temp;
char ctemp;
while(~scanf("%d%d",&y,&x) && x)
{
x--;
y--;
top1=top2=bottom1=bottom2=0;
memset(vis1,0,sizeof vis1);
memset(vis2,0,sizeof vis2);
memset(head,-1,sizeof head);
total=0;
while(!stk.empty()) stk.pop();
for(i=0;i<9;i++)
{
ctemp=getchar();
if(ctemp=='\n' || ctemp==' ')
{
i--;
continue;
}
if(ctemp=='W')mp[i]=1;
else if(ctemp=='B') mp[i]=3;
else if(ctemp=='R') mp[i]=5;
else if(ctemp=='E') mp[i]=0;
}
pushtarget(8,0);
temp=0;
for(i=8;i>=0;i--)
{
if(i!=x*3+y) temp=temp*7+1;
else temp*=7;
}
if(vis2[hashval(temp)])
{
printf("0\n");
continue;
}
vis1[hashval(temp)]=1;
que1[bottom1].step=0;
que1[bottom1].state=temp;
bottom1++;
printf("%d\n",bfs());
}
}POJ-3131-Cubic Eight-Puzzle(双向BFS+哈希)的更多相关文章
- UVA-1604 Cubic Eight-Puzzle (双向BFS+状态压缩+限制搜索层数)
题目大意:立体的八数码问题,一次操作是滚动一次方块,问从初始状态到目标状态的最少滚动次数. 题目分析:这道题已知初始状态和目标状态,且又状态数目庞大,适宜用双向BFS.每个小方块有6种状态,整个大方格 ...
- poj 3131 Cubic Eight-Puzzle 双向广搜 Hash判重
挺不错的题目,很锻炼代码能力和调试能力~ 题意:初始格子状态固定,给你移动后格子的状态,问最少需要多少步能到达,如果步数大于30,输出-1. 由于单向搜索状态太多,搜到二十几就会爆了,所以应该想到双向 ...
- POJ 1915 经典马步 双向bfs
拿这个经典题目开刀...........可是双向时间优势在这题上的效果不太明显 #include <iostream> #include <algorithm> #includ ...
- Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...
- POJ 3170 Knights of Ni (暴力,双向BFS)
题意:一个人要从2先走到4再走到3,计算最少路径. 析:其实这个题很水的,就是要注意,在没有到4之前是不能经过3的,一点要注意.其他的就比较简单了,就是一个双向BFS,先从2搜到4,再从3到搜到4, ...
- POJ 3126 Prime Path 解题报告(BFS & 双向BFS)
题目大意:给定一个4位素数,一个目标4位素数.每次变换一位,保证变换后依然是素数,求变换到目标素数的最小步数. 解题报告:直接用最短路. 枚举1000-10000所有素数,如果素数A交换一位可以得到素 ...
- POJ 1915-Knight Moves (单向BFS && 双向BFS 比)
主题链接:Knight Moves 题意:8个方向的 马跳式走法 ,已知起点 和终点,求最短路 研究了一下双向BFS,不是非常难,和普通的BFS一样.双向BFS只是是从 起点和终点同一时候開始搜索,可 ...
- [poj] 2549 Sumsets || 双向bfs
原题 在集合里找到a+b+c=d的最大的d. 显然枚举a,b,c不行,所以将式子移项为a+b=d-c,然后双向bfs,meet int the middle. #include<cstdio&g ...
- POJ——3126Prime Path(双向BFS+素数筛打表)
Prime Path Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16272 Accepted: 9195 Descr ...
随机推荐
- RabbitMQ之任务队列【译】
在第一个教程里面,我们写了一个程序从一个有名字的队列中发送和接收消息,在这里我们将要创建一个分发耗时任务给多个worker的任务队列. 任务队列核心思想就是避免执行一个资源密集型的任务,而程序要等待其 ...
- (壹)、java面向对象详解
面向对象的概述: 1.用java语言对现实生活中的事物进行描述.通过类的形式来体现的. 2.怎么描述呢? 对于事物描述通常只关注两方面. 一个是属性,一个是行为. 3.成员变量和局部变量的区别: ①成 ...
- hdu6153 扩展kmp求一个字符串的后缀在另一个字符串出现的次数。
/** 题目:hdu6153 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6153 题意:给定两个串,求其中一个串t的每个后缀在另一个串s中出现的次数乘以 ...
- SQL Server 数据库同步,订阅、发布、复制、跨服务器
随便说两句 折腾了一周,也算把数据库同步弄好了.首先局域网内搭建好,进行各种测试,弄的时候各种问题,弄好以后感觉还是挺简单的.本地测试好了,又在服务器进行测试,主要的难点就是跨网段同步,最后也解决了, ...
- mysql插入多行数据
表结构如图:
- (转)spring IOC、DI理解
转自: http://www.cnblogs.com/xdp-gacl/p/4249939.html 个人理解: IOC控制反转,反转的是获取依赖对象的方式.传统的应用在存在依赖关系时,比如A依赖于B ...
- Mysql命令行添加用户并且给予远程访问服务器的权限
--查询用户SELECT User, Password, Host FROM user; --创建一个用户,任意主机可以登录%,密码是123456 '; -- 给用户赋予所有权限 GRANT ALL ...
- 利用LoadRunner判断HTTP服务器的返回状态
利用LoadRunner判断HTTP服务器的返回状态第一种方法:是利用LR的内置函数web_get_int_property.举例:#include "web_api.h"Acti ...
- LoadRunner中winsocket协议学习
首先让我们先看一下loadrunner- winsock 函数 一览表: lrs_accept_connection 接受侦听套接字连接 lrs_close_socket 关闭打开的套接 ...
- Linux atop监控工具部署
一.atop简介 atop是一款用于监控Linux系统资源与进程的工具,它以一定的频率记录系统的运行状态,所采集的数据包含系统资源(CPU.内存.磁盘和网络)使用情况和进程运行情况,并能以日志文件的方 ...