POJ 2697 A Board Game(Trie判重+BFS)
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 551 | Accepted: 373 |
Description
- 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
Output
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)的更多相关文章
- 洛谷 P1379 八数码难题 Label:判重&&bfs
特别声明:紫书上抄来的代码,详见P198 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给 ...
- 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 ...
- POJ 2697 A Board Game (bfs模拟)
比较水的一道题,在4*4的棋盘上有黑白子,现在有某种移动方式,问能否通过它将棋盘从某个状态移动到另一种状态 只要想好怎么保存hash表来去重,其他就差不多了... #include <iostr ...
- 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 ...
- POJ 1945 暴搜+打表 (Or 暴搜+判重)
思路: 呃呃 暴搜+打表 暴搜的程序::稳稳的TLE+MLE (但是我们可以用来打表) 然后我们就可以打表过了 hiahiahia 可以证明最小的那个数不会超过200(怎么证明的我也不知道),然后就直 ...
- poj 1465 Multiple(bfs+余数判重)
题意:给出m个数字,要求组合成能够被n整除的最小十进制数. 分析:用到了余数判重,在这里我详细的解释了.其它就没有什么了. #include<cstdio> #include<cma ...
- POJ 3668 Game of Lines (暴力,判重)
题意:给定 n 个点,每个点都可以和另一个点相连,问你共有多少种不同斜率的直线. 析:那就直接暴力好了,反正数也不大,用set判重就好,注意斜率不存在的情况. 代码如下: #include <c ...
- poj 3131 双向搜索+hash判重
题意: 初始状态固定(朝上的全是W,空格位置输入给出),输入初始状态的空格位置,和最终状态朝上的位置,输出要多少步才能移动到,超过30步输出-1. 简析: 每一个格子有6种状态,分别是 0WRB, 1 ...
- POJ 2458 DFS+判重
题意: 思路: 搜+判重 嗯搞定 (听说有好多人用7个for写得-.) //By SiriusRen #include <bitset> #include <cstdio>0 ...
随机推荐
- nodejs随记01
EventEmitter var stream = require('stream'); var Readable = stream.Readable; //写入类(http-req就是),初始化时会 ...
- css3 -- 文本
1.坐标轴: 上左为负数 下右为正数 2.text-shadow E{text-shadow:x y color:} 还可以负数实现 E{text-shadow:x y blur-radius col ...
- android测试点汇总
Android的功能测试点 安装\卸载 App具体功能点 联网(默认的联网方式是什么?Wifi orSim卡?网络切换是否有相应的提示说明?飞行模式) 程序进入输入功能时,是否正常弹出键盘;键盘是否遮 ...
- 【CLR in c#】参数
1.可选参数和命名参数 设计一个参数时,可为部分或全部参数分配默认值,调用这些方法的代码可以选择不指定部分实参,接受默认值,还可以通过制定参数名称的方式传递实参.如下 class CLR可选参数 { ...
- BestCoder Round #65
博弈 1002 ZYB's Game 题意:中文 分析:假定两个人是绝顶聪明的,一定会采取最优的策略.所以如果选择X的左边的一个点,那么后手应该选择X的右边对称的点,如果没有则必输,否则必胜,然后再分 ...
- Android自动截屏小脚本
@echo off echo * 截图文件将保存在 E:\pic下,以当前日期+时间命名. echo ================================================= ...
- Codeforces 696D Legen...(AC自动机 + 矩阵快速幂)
题目大概说给几个字符串,每个字符串都有一个开心值,一个串如果包含一次这些字符串就加上对应的开心值,问长度n的串开心值最多可以是多少. POJ2778..复习下..太弱了都快不会做了.. 这个矩阵的乘法 ...
- jquery ajax 提交信息后等待返回的提示信息
最简单的方法: http://bbs.csdn.net/topics/390584283?page=1 $('#click').click(function){ $('#data').html('&l ...
- BZOJ4360 : achievement
对于$mode=0$的情况: 假设已经知道了最终要做哪些成就,那么这些成就一定是按$b$递减做的. 将成就按$b$从大到小排序,考虑往已选集合里新加一个成就. 假设该成就前面有$t$个已选成就,后面成 ...
- (转)linux命令行下的ftp 多文件下载和目录下载
link:http://yahoon.blog.51cto.com/13184/200991 目标ftp服务器是一个非标准端口的ftp 1.通过shell登录 #ftp //shell下输入 ...