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 ...
随机推荐
- no-jquery 02 DOM
DOM Manipulation Creating Elements // IE 5.5+ document.createElement('div'); Inserting Elements Befo ...
- PHP 使用 OSS 批量上传图片
<?php set_time_limit(0); // 引入自动加载类// 确保路径是否正确 require_once 'autoload.php'; // 确定参数 需要申请 $accessK ...
- Scau 8633 回文划分 mancher + dp
时间限制:1000MS 内存限制:1000K 提交次数: 通过次数: 题型: 编程题 语言: G++;GCC Description 我们说一个字符串是回文串,那么意味着这个串从两边读起来的字母都是一 ...
- Money类型转化为String去除小数点后0解决方法
Money类型转化为String去除小数点后0从数据库提取Money类型后,字符串如:1212.0000 如何使其成为1212 注:去掉了小数点 如果是:1212.0100 使 ...
- ccc 音乐播放
cc.Class({ extends: cc.Component, properties: { musicPlayer: { default: null, type: cc.AudioSource } ...
- 【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树
[BZOJ3531][Sdoi2014]旅行 Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天 ...
- Qt搭建多线程Server
起因是MySQL在Android上没有驱动.也就是说,移动端想要访问远程数据库,必须通过一台(或多台)PC进行中转. 中转PC作为Server,接受来自移动端Socket访问数据库的要求,Server ...
- Android 情景模式设置
情景模式的设置大家应当相当熟悉了,但是在Android中如何通过自己的程序进行情景模式的设置呢,情景模式分为多种多种,即可以使用系统自带的,也可 以使用自定义的,但是在开发某些程序时,可能需要在程序中 ...
- BZOJ3212 Pku3468 A Simple Problem with Integers 题解
题目大意: 一个数列,有两个操作:1.修改操作,将一段区间内的数加上c:2.查询操作,查询一段区间内的数的和. 思路: 线段树裸题,区间修改.区间查询,维护和以及加上的数,由于无序,不需要向下推标记, ...
- 【BZOJ】1987: Zju2672 Fibonacci Subsequence
题意 给出一个序列\(A\),求一个最长的满足fib性质的子序列,输出其长度及其元素(如果多种方案,输出位置最靠前的).(\(n \le 3000\)) 题解 容易想到dp,即\(d(i, j)\)表 ...