Let's play a puzzle using eight cubes placed on a 3 x 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 the 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 are colored in the same way as shown in Figure 3. The opposite
faces have the same color.
Figure 3: Coloring of a cube


1.Initial Board State: Eight cubes are placed on the 3 x 3 board leaving one empty square. All the
cubes have the same orientation as shown in Figure 4. 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 4: Initial board state
2.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 5 shows an example.
Figure 5: Rolling a cube

3.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.
4.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
F
11 F21 F31
F
12 F22 F32
F
13 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
F
3j, separated by a space. Character Fij indicates the top color of the cube, if any, at 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.
3618 - Cubic Eight-Puzzle 2/3
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

解题报告

难度。。很大,BFS这个没有疑问,那么究竟是A*还是双广呢,由于本题的状态数很多,且转移方程很麻烦,所以首先考虑A*.

估价函数这里不在多说(其实是我忘了),但提交后TLE...,CODE如下

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <ctime>
using namespace std;
const int MaxHashSize = ;
const int MaxState = ;
int tot,target[];
char g[];
int dir[][] = {,,,-,-,,,};
int getdia[][] = {,,,,,,,,,,,,,,,,,,,,,,,}; typedef struct status
{
char pos;
char step;
int g;
char h;
friend bool operator < (const status& a ,const status& b)
{
if (a.step + a.h < b.step + b.h)
return false;
if (a.step + a.h == b.step + b.h && a.step < b.step)
return false;
return true;
} }; priority_queue<status> q; status start;
int Head[MaxHashSize],Next[MaxState];
status st[MaxState];
void init_Hash()
{
memset(Head,-,sizeof(Head));
} int GetHashValue(status &x)
{
return x.g % MaxHashSize;
} bool insert_Hash(int id)
{
int h = GetHashValue(st[id]);
int u = Head[h];
while(u != -)
{
if (st[u].g == st[id].g)
return false;
u = Next[u];
}
Next[id] = Head[h];
Head[h] = id;
return true;
} int caculateh(status &x)
{
int res = ;
int ok = ;
for(int i = ; i < ; ++ i)
{
int temp = ;
for(int j = ; j < ; ++ j)
{
int s = (x.g >> (*i + j)) & ;
temp |= (s << j);
}
if ( (temp == || temp == ) && g[i] != 'W')
res ++ ;
else if ( (temp == || temp == ) && g[i] !='R')
res ++;
else if ( (temp == || temp == ) && g[i] != 'B')
res ++;
else if (temp == && g[i] != 'E' )
{
res ++;
ok = ;
} }
if (ok)
return res;
else
return res - ; } int bfs()
{
int front = ,rear = ;
q.push(start);
while(!q.empty())
{
status ss = q.top();q.pop();
st[front++] = ss;
if (ss.h == )
return ss.step;
if (ss.h + ss.step > )
return -;
int pos = ss.pos;
int x = pos / ;
int y = pos % ;
int step = ss.step;
int g = ss.g;
for(int i = ; i < ; ++ i)
{
int newx = x + dir[i][];
int newy = y + dir[i][];
if (newx >= || newx < || newy >= || newy < )
continue;
int newpos = newx * + newy;
status ns = ss;
int temp = ;
for(int j = ; j < ; ++ j)
{
int s = (g >> (newpos * + j) ) & ;
temp |= (s << j);
}
int sis = getdia[temp][i];
for(int j = ; j < ;++ j)
ns.g |= ( << (newpos* + j));
for(int j = ; j < ; ++ j)
if (sis >> j & )
ns.g |= ( << pos * + j);
else
ns.g &= ~( << pos * + j);
ns.step = step + ;
ns.pos = newpos;
ns.h = caculateh(ns);
st[rear] = ns;
if (insert_Hash(rear))
{
q.push(ns);
rear++;
}
}
}
return -;
} int main(int argc, char * argv[])
{
int kk = clock();
int s1,s2;
while(scanf("%d%d%*c",&s1,&s2) && s1)
{
tot = ;
for(int i = ; i < ; ++ i)
scanf("%c%*c",&g[i]);
int fp = (s2-) * + s1 - ;
start.pos = fp;
start.g = ;
init_Hash();
for(int i = ; i < ; ++ i)
start.g |= ( << (*fp+i));
st[] = start;
insert_Hash();
start.h = caculateh(start);
start.step = ;
while(!q.empty())
q.pop();
cout << bfs() << endl;
}
cout << "Time use " << clock() - kk << endl;
return ;
}

这里的代码中有Clock(),大家可以试试几组数据,30步的极限或者-1,速度非常慢。。(无法忍受)

那么,我们只能改用双广了,因为末状态有256种,所以我们用一个dfs把末状态压进去,提交后AC~

顺便多题一句双广复杂度是 2*n^(a/2) ,而单向的是n^a,code 如下

 #include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int MaxHashSize = ;
const int MaxState = ;
int tot,target[],ssl;
char g[];
int dir[][] = {,,,-,-,,,};
int getdia[][] = {,,,,,,,,,,,,,,,,,,,,,,,}; typedef struct status
{
char pos;
char step;
int g;
}; status start;
int Head[MaxHashSize],Next[MaxState];
int Head2[MaxHashSize],Next2[MaxState];
status st[MaxState];
status st2[MaxState]; void init_Hash()
{
memset(Head,-,sizeof(Head));
memset(Head2,-,sizeof(Head));
} int GetHashValue(status &x)
{
return x.g % MaxHashSize;
} bool insert_Hash(int id ,int l)
{
int h;
if (l == )
h = GetHashValue(st[id]);
else
h = GetHashValue(st2[id]);
int u;
if (l == )
u = Head[h];
else
u = Head2[h]; while(u != -)
{
if (l == )
{
if (st[u].g == st[id].g)
return false;
u = Next[u];
}
else
{
if (st2[u].g == st2[id].g)
return false;
u = Next2[u];
}
}
if (l == )
{
Next[id] = Head[h];
Head[h] = id;
}
else
{
Next2[id] = Head2[h];
Head2[h] = id;
}
return true;
} int meet(int id,int l)
{
int u,h;
if (l == )
{
h = GetHashValue(st[id]);
int u = Head2[h];
while(u != -)
{
if (st2[u].g == st[id].g)
return st[id].step + st2[u].step;
u = Next2[u];
} return -;
}
else
{
h = GetHashValue(st2[id]);
int u = Head[h];
while(u != -)
{
if (st[u].g == st2[id].g)
return st[u].step + st2[id].step;
u = Next[u];
} return -;
}
} int bfs()
{
int front = ,rear = ;
int front2 = , rear2 = ;
while(front < rear && front2 < rear2)
{
if ()
{
status ss = st[front++] ;
int ans = meet(front-,);
if (ans != -)
return ans > ? - : ans;
if (ss.step >= )
return -;
int pos = ss.pos;
int x = pos / ;
int y = pos % ;
int step = ss.step;
int g = ss.g;
for(int i = ; i < ; ++ i)
{
int newx = x + dir[i][];
int newy = y + dir[i][];
if (newx >= || newx < || newy >= || newy < )
continue;
int newpos = newx * + newy;
status ns = ss;
int temp = ;
for(int j = ; j < ; ++ j)
{
int s = (g >> (newpos * + j) ) & ;
temp |= (s << j);
}
int sis = getdia[temp][i];
for(int j = ; j < ;++ j)
ns.g |= ( << (newpos* + j));
for(int j = ; j < ; ++ j)
if (sis >> j & )
ns.g |= ( << pos * + j);
else
ns.g &= ~( << pos * + j);
ns.step = step + ;
ns.pos = newpos;
st[rear] = ns;
if (insert_Hash(rear,))
{
rear++;
}
}
}
status ss = st2[front2++] ;
int ans = meet(front2-,);
if (ans != -)
return ans > ? - : ans;
if (ss.step >= )
return -;
int pos = ss.pos;
int x = pos / ;
int y = pos % ;
int step = ss.step;
int g = ss.g;
for(int i = ; i < ; ++ i)
{
int newx = x + dir[i][];
int newy = y + dir[i][];
if (newx >= || newx < || newy >= || newy < )
continue;
int newpos = newx * + newy;
status ns = ss;
int temp = ;
for(int j = ; j < ; ++ j)
{
int s = (g >> (newpos * + j) ) & ;
temp |= (s << j);
}
int sis = getdia[temp][i];
for(int j = ; j < ;++ j)
ns.g |= ( << (newpos* + j));
for(int j = ; j < ; ++ j)
if (sis >> j & )
ns.g |= ( << pos * + j);
else
ns.g &= ~( << pos * + j);
ns.step = step + ;
ns.pos = newpos;
st2[rear2] = ns;
if (insert_Hash(rear2,))
{
rear2++;
}
}
}
return -;
} void dfs(int n,int temp)
{
if (n == )
{
st2[tot].g = temp;
st2[tot].step = ;
insert_Hash(tot,);
st2[tot++].pos = ssl;
}
else
{
int f;
if (g[n] == 'W')
{
f = temp;
dfs(n+,f);
f |= ( << (*n));
dfs(n+,f);
}
else if(g[n] == 'R')
{
f = temp;
f |= ( << (*n+));
dfs(n+,f);
f |= ( << *n);
dfs(n+,f);
}
else if(g[n] == 'B')
{
f = temp;
f |= ( << *n+);
dfs(n+,f);
f |= ( << *n);
dfs(n+,f);
}
else if(g[n] == 'E')
{
f = temp;
for(int j = ; j < ; ++ j)
f |= ( << *n + j);
dfs(n+,f);
}
}
} int main(int argc, char * argv[])
{
int s1,s2;
while(scanf("%d%d%*c",&s1,&s2) && s1)
{
tot = ;
for(int i = ; i < ; ++ i)
{
scanf("%c%*c",&g[i]);
if (g[i] == 'E')
ssl = i;
}
int fp = (s2-) * + s1 - ;
start.pos = fp;
start.g = ;
init_Hash();
dfs(,);
for(int i = ; i < ; ++ i)
start.g |= ( << (*fp+i));
st[] = start;
insert_Hash(,);
start.step = ;
cout << bfs() << endl;
}
return ;
}

UVA_Cubic Eight-Puzzle UVA 1604的更多相关文章

  1. UVA_Digit Puzzle UVA 12107

    If you hide some digits in an integer equation, you create a digit puzzle. The figure below shows tw ...

  2. uva 227 Puzzle (UVA - 227)

    感慨 这个题实在是一个大水题(虽然说是世界决赛真题),但是它给出的输入输出数据,标示着老子世界决赛真题虽然题目很水但是数据就能卡死你...一直pe pe直到今天上午AC...无比感慨...就是因为最后 ...

  3. Puzzle UVA - 227 PE代码求大佬指点

    ​ A children's puzzle that was popular 30 years ago consisted of a 5×5 frame which contained 24 smal ...

  4. UVA 1604:Cubic Eight-Puzzle(模拟,BFS Grade C)

    题意: 3*3方格,有一个是空的.其他的每个格子里有一个立方体.立方体最初上下白色,前后红色,左右蓝色.移动的方式为滚.给出初态空的位置,终态上面颜色情况,问最少多少步能到达.如果超过30步不能到达, ...

  5. uva 227 Puzzle

     Puzzle  A children's puzzle that was popular 30 years ago consisted of a 5x5 frame which contained ...

  6. UVA 227 Puzzle - 输入输出

    题目: acm.hust.edu.cn/vjudge/roblem/viewProblem.action?id=19191 这道题本身难度不大,但输入输出时需要特别小心,一不留神就会出问题. 对于输入 ...

  7. UVA 277 Puzzle

    题意:输入5x5的字符串,输入操作,要求输出完成操作后的字符串. 注意:①输入的操作执行可能会越界,如果越界则按题目要求输出不能完成的语句. ②除了最后一次的输出外,其他输出均要在后面空一行. ③操作 ...

  8. UVA 227 Puzzle(基础字符串处理)

    题目链接: https://cn.vjudge.net/problem/UVA-227 /* 问题 输入一个5*5的方格,其中有一些字母填充,还有一个空白位置,输入一连串 的指令,如果指令合法,能够得 ...

  9. uva live 12846 A Daisy Puzzle Game

    假设下一个状态有必败.那么此时状态一定是必胜,否则此时状态一定是必败 状压DP #include<iostream> #include<map> #include<str ...

随机推荐

  1. 利用jquery表格添加一行并在每行第一列大写字母显示实现方法

    表格添加一行并在每行第一列大写字母显示jquery实现方法 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN& ...

  2. poj2196

    Specialized Four-Digit Numbers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7238   A ...

  3. VS快捷编码方式

    概念: 代码段是将预先定义好的可重用代码块快速插入到代码文件中,代码段提高了开发效率,增强了代码的可重用性:既节约了时间,又实现了不同开发人员间代码的共享.同时也可保证同一项目中代码风格的统一.   ...

  4. (转)25个增强iOS应用程序性能的提示和技巧--中级篇

    在性能优化时,当你碰到一些复杂的问题,应该注意和使用如下技巧: 9.重用和延迟加载View10.缓存.缓存.缓存11.考虑绘制12.处理内存警告13.重用花销很大的对象14.使用Sprite Shee ...

  5. Oracle通过指令创建用户

    Oracle作为世界上使用最广泛的关系数据库,对于客户很多每天海量数据的公司是首要选择.我们公司在双十一期间,曾发生过每网点每天1G多的扫描数据量,全国有六千多个网点,每天每时不停读写数据库,而数据库 ...

  6. Vijos1051. 送给圣诞夜的极光

    试题请參见: https://vijos.org/p/1051 题目概述 圣诞老人回到了北极圣诞区, 已经快到12点了. 也就是说极光表演要開始了. 这里的极光不是极地特有的自然极光景象. 而是圣诞老 ...

  7. [Git] set-upstream

    When you want to push your local branch to remote branch, for the first push: git push --set-upstrea ...

  8. hdu4506小明系列故事——师兄帮帮忙 (用二进制,大数高速取余)

    Problem Description 小明自从告别了ACM/ICPC之后,就開始潜心研究数学问题了,一则能够为接下来的考研做准备,再者能够借此机会帮助一些同学,尤其是美丽的师妹.这不,班里唯一的女生 ...

  9. iframe框架默认占满整个屏幕

    <script language="JavaScript"> if (window != top) { top.location.href = location.hre ...

  10. 一道movfuscator混淆过的简单逆向

        月赛中出了道经过movfuscator混淆的逆向题目,记录一下过程.跑起来发现需要用户输入长度为20的字符串,我尝试着输入了几次都是直接退出了,没有任何提示.用IDA打开,题目里面几乎全是mo ...