A Board Game
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 551   Accepted: 373

Description

Dao was a simple two-player board game designed by Jeff Pickering and Ben van Buskirk at 1999. A variation of it, called S-Dao, is a one-player game. In S-Dao, the game board is a 4 * 4 square with 16 cells. There are 4 black stones and 4 white stones placed on the game board randomly in the beginning. The player is given a final position and asked to play the game using the following rules such that the final position is reached using the minimum number of moves:

      1. You first move a white stone, and then a black stone. You then alternatively move a white stone and a black stone.
      2. A stone can be moved horizontally, vertically or diagonally. A stone must be moved in a direction until the boarder or another stone is encountered. There is no capture or jump.
    3. During each move, you need to move a stone of the right color. You cannot pass.

An example of a sequence of legal moves is shown in the following figure. This move sequence takes 4 moves. This is not a sequence of legal moves 
 
using the least number of moves assume the leftmost board is the initial position and the rightmost board is the final position. A sequence of moves using only 3 moves is shown below. 
 
Given an initial position and a final position, your task is to report the minimum number of moves from the initial position to the final position.

Input

The first line contains the number of test cases w, w <= 6. Then the w test cases are listed one by one. Each test case consists of 8 lines, 4 characters per line. The first 4 lines are the initial board position. The remaining 4 lines are the final board position. The i-th line of a board is the board at the i-th row. A character 'b' means a black stone, a character 'w' means a white stone, and a '*' means an empty cell.

Output

For each test case, output the minimum number of moves in one line. If it is impossible to move from the initial position to the final position, then output -1.

Sample Input

2
w**b
*wb*
*bw*
b**w
w**b
*wb*
*bw*
bw**
w**b
*b**
**b*
bwww
w**b
*bb*
****
bwww

Sample Output

1
3

题目链接:POJ 2697

题如其名,很无聊,难怪题目里的S-Dao是一个人玩的游戏,给你一个4*4的棋盘和4颗黑棋、4颗白旗,每一次可以向八个方向移动,但是只能撞到边界或者撞到棋子才能停止移动,求初始态到目标态最少的移动次数,这题由于每个格子的颜色不是唯一的,康托不好用,只能用STL或者字典树,然后看一共有多少种状态,显然是$\binom{16}{4} * \binom{12}{4} = 900900$,然而想想STL这么慢还是字典树吧,顺便再熟练一下数组版字典树的写法,虽然代码量有点大,但是细心点还是不会错的,写斜方向移动函数的时候突然感觉有点想起以前玩魔方的公式了,怀念1s。

代码:

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <bitset>
#include <string>
#include <deque>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=900900+7;
struct info
{
char st[4][4];
bool bw;
int step;
inline bool operator==(const info &t)const
{
for (int i=0; i<4; ++i)
for (int j=0; j<4; ++j)
if(st[i][j]!=t.st[i][j])
return false;
return true;
}
inline void Lmove(const int &x,const int &y)
{
int yy=y;
while (yy-1>=0&&st[x][yy-1]=='0')
--yy;
swap(st[x][y],st[x][yy]);
++step;
bw^=1;
}
inline void Rmove(const int &x,const int &y)
{
int yy=y;
while (yy+1<4&&st[x][yy+1]=='0')
++yy;
swap(st[x][y],st[x][yy]);
++step;
bw^=1;
}
inline void Umove(const int &x,const int &y)
{
int xx=x;
while (xx-1>=0&&st[xx-1][y]=='0')
--xx;
swap(st[x][y],st[xx][y]);
++step;
bw^=1;
}
inline void Dmove(const int &x,const int &y)
{
int xx=x;
while (xx+1<4&&st[xx+1][y]=='0')
++xx;
swap(st[x][y],st[xx][y]);
++step;
bw^=1;
}
inline void RU(const int &x,const int &y)
{
int xx=x;
int yy=y;
while (xx-1>=0&&yy+1<4&&st[xx-1][yy+1]=='0')
--xx,++yy;
swap(st[x][y],st[xx][yy]);
++step;
bw^=1;
}
inline void RD(const int &x,const int &y)
{
int xx=x;
int yy=y;
while (xx+1<4&&yy+1<4&&st[xx+1][yy+1])
++xx,++yy;
swap(st[x][y],st[xx][yy]);
++step;
bw^=1;
}
inline void LU(const int &x,const int &y)
{
int xx=x;
int yy=y;
while (xx-1>=0&&yy-1>=0&&st[xx-1][yy-1]=='0')
--xx,--yy;
swap(st[x][y],st[xx][yy]);
++step;
bw^=1;
}
inline void LD(const int &x,const int &y)
{
int xx=x;
int yy=y;
while (xx+1<4&&yy-1>=0&&st[xx+1][yy-1]=='0')
++xx,--yy;
swap(st[x][y],st[xx][yy]);
++step;
bw^=1;
}
};
struct Trie
{
int nxt[3];
inline void init()
{
nxt[0]=nxt[1]=nxt[2]=0;
}
};
Trie L[N*3];
int tot;
info S,T;
enum {B=true,W=false}; void init()
{
L[0].init();
tot=1;
}
bool update(const info &t)
{
int now=0;
bool any=false;
for (int i=0; i<16; ++i)
{
int v=t.st[i>>2][i%4]-'0';
if(!L[now].nxt[v])
{
L[tot].init();
L[now].nxt[v]=tot++;
any=true;
}
now=L[now].nxt[v];
}
return any;
}
int bfs(const info &s)
{
queue<info>Q;
Q.push(s);
update(s);
info now,v;
while (!Q.empty())
{
now=Q.front();
if(now==T)
return now.step;
Q.pop();
if(!now.bw)///白色
{
for (int i=0; i<16; ++i)
{
if(now.st[i>>2][i%4]=='1')
{
v=now;
v.Dmove(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.Umove(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.Lmove(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.Rmove(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.LU(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.RU(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.LD(i>>2,i%4);
if(update(v))
Q.push(v);
}
}
}
else///黑色
{
for (int i=0; i<16; ++i)
{
if(now.st[i>>2][i%4]=='2')
{
v=now;
v.Dmove(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.Umove(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.Lmove(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.Rmove(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.LU(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.RU(i>>2,i%4);
if(update(v))
Q.push(v);
v=now;
v.LD(i>>2,i%4);
if(update(v))
Q.push(v);
}
}
}
}
return -1;
}
int main(void)
{
int tcase,i,j;
scanf("%d",&tcase);
getchar();
while (tcase--)
{
init();
for (i=0; i<4; ++i)
{
for (j=0; j<4; ++j)
{
scanf("%c",&S.st[i][j]);
if(S.st[i][j]=='*')
S.st[i][j]='0';
else if(S.st[i][j]=='w')
S.st[i][j]='1';
else
S.st[i][j]='2';
}
getchar();
}
S.step=0;
S.bw=W;
for (i=0; i<4; ++i)
{
for (j=0; j<4; ++j)
{
scanf("%c",&T.st[i][j]);
if(T.st[i][j]=='*')
T.st[i][j]='0';
else if(T.st[i][j]=='w')
T.st[i][j]='1';
else
T.st[i][j]='2';
}
getchar();
}
printf("%d\n",bfs(S));
}
return 0;
}

POJ 2697 A Board Game(Trie判重+BFS)的更多相关文章

  1. 洛谷 P1379 八数码难题 Label:判重&&bfs

    特别声明:紫书上抄来的代码,详见P198 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给 ...

  2. poj 2697 A Board Game(bfs+hash)

    Description Dao was a simple two-player board game designed by Jeff Pickering and Ben van Buskirk at ...

  3. POJ 2697 A Board Game (bfs模拟)

    比较水的一道题,在4*4的棋盘上有黑白子,现在有某种移动方式,问能否通过它将棋盘从某个状态移动到另一种状态 只要想好怎么保存hash表来去重,其他就差不多了... #include <iostr ...

  4. poj 1564 Sum It Up | zoj 1711 | hdu 1548 (dfs + 剪枝 or 判重)

    Sum It Up Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Sub ...

  5. POJ 1945 暴搜+打表 (Or 暴搜+判重)

    思路: 呃呃 暴搜+打表 暴搜的程序::稳稳的TLE+MLE (但是我们可以用来打表) 然后我们就可以打表过了 hiahiahia 可以证明最小的那个数不会超过200(怎么证明的我也不知道),然后就直 ...

  6. poj 1465 Multiple(bfs+余数判重)

    题意:给出m个数字,要求组合成能够被n整除的最小十进制数. 分析:用到了余数判重,在这里我详细的解释了.其它就没有什么了. #include<cstdio> #include<cma ...

  7. POJ 3668 Game of Lines (暴力,判重)

    题意:给定 n 个点,每个点都可以和另一个点相连,问你共有多少种不同斜率的直线. 析:那就直接暴力好了,反正数也不大,用set判重就好,注意斜率不存在的情况. 代码如下: #include <c ...

  8. poj 3131 双向搜索+hash判重

    题意: 初始状态固定(朝上的全是W,空格位置输入给出),输入初始状态的空格位置,和最终状态朝上的位置,输出要多少步才能移动到,超过30步输出-1. 简析: 每一个格子有6种状态,分别是 0WRB, 1 ...

  9. POJ 2458 DFS+判重

    题意: 思路: 搜+判重 嗯搞定 (听说有好多人用7个for写得-.) //By SiriusRen #include <bitset> #include <cstdio>0 ...

随机推荐

  1. jquery的隐藏与显示

    ###显示与隐藏,通过用hide()和show()函数来实现 语法: $(selector).hide(speed,callback); $(selector).show(speed,callback ...

  2. jq ajax遇到的错误集合

    一.错误: Uncaught InvalidStateError: Failed to read the 'selectionDirection' property from 'HTMLInputEl ...

  3. The 2015 China Collegiate Programming Contest E. Ba Gua Zhen hdu 5544

    Ba Gua Zhen Time Limit: 6000/4000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total ...

  4. XIII Open Cup named after E.V. Pankratiev. GP of America

    A. Explosions 注意到将炸弹按坐标排序后,每个炸弹直接引爆和间接引爆的都是连续的一段区间,因此只需要求出每个炸弹能间接炸到的最左和最右的炸弹即可. 建立图论模型,炸弹$i$向炸弹$j$连单 ...

  5. BZOJ3583 : 杰杰的女性朋友

    将$I$转置,设$G=OI$,则$ans=G^0+G^1+...+G^d$. 注意到$G^d=O(IO)^{d-1}I$,而$IO$是大小为$k\times k$的矩阵,可以通过倍增在$O(k^3\l ...

  6. 同引擎mysql数据库转导快

    mysql数据库从一个表导入到另外一个表,数据库表引擎类型相同速度会快很多,相反,慢得离奇,5w,相同从myisam到myisam一或两分钟,从myisam到innodb要1到2个小时. [注意:最近 ...

  7. 图解Storm

    问题导读:1.你认为什么图形可以显示hadoop与storm的区别?(电梯)2.本文是如何形象讲解hadoop与storm的?(离线批量处理.实时流式处理)3.hadoop map/reduce对应s ...

  8. CUDA程序设计(二)

    算法设计:直方图统计 直方图频数统计,也可以看成一个字典Hash计数.用处不是很多,但是涉及CUDA核心操作:全局内存.共享内存.原子函数. 1.1  基本串行算法 这只是一个C语言练习题. #def ...

  9. 转:Web页面通过URL地址传递参数常见问题及检测方法

    Web页面即我们在浏览器中所看到的网页,在Web应用程序中,其页面往往需要进行动态切换和数据交互,页面间的数据常规传递方法有多种,本文主要介绍Web页面处理程序中常见的URL地址参数传递方法,包括概述 ...

  10. 彻底弄明白之数据结构中的排序七大算法-java实现

    package ds; /* * author : codinglion * contact: chenyakun@foxmail.com */ import java.util.Random; pu ...