ZOJ - 1505 Solitaire 【双向BFS】
题目链接
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1505
题意
一个8 * 8 的棋盘上面有四个棋子
棋子可以上下左右移动,如果隔壁有个棋子 那就可以跳一步,只能跳一步。
给出 初始状态,和末尾状态 求能不能在8步之内达到
思路
如果是单向BFS (4 * 4)^ 8 = 2 ^ 32 个状态数
太大了
采用双向广搜
状态数 就是
(4 * 4)^ 4 * 2 = 2 ^ 17
因为内存只有32mb
然后我想 用八进制的数字 来存状态
然后转化成十进制
就是 8 ** 8 = 16777216
16777216 * 4 / 1024 = 65536kb = 64mb
爆内存了。。
然后后来想想,既然用了双向广搜来减少时间复杂度了,,不如直接用map 标记 也只是增加了log 的时间复杂度
就试试了。。
对了 那个状态 对四个棋子的位置 一定要排序后再转值 不然可能两个状态是一样的 但是得到的值确实不一样的
然后就A了。
AC代码
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <ctype.h>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <set>
#include <list>
#include <numeric>
#include <sstream>
#include <iomanip>
#include <limits>
#define CLR(a, b) memset(a, (b), sizeof(a));
#define pb push_back
#define bug puts("***bug***");
#define fi first
#define se second
#define L(on) ((on)<<1)
#define R(on) (L(on) | 1)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define syn_close ios::sync_with_stdio(false); cin.tie(0);
#define sp system("pause");
//#define gets gets_s
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <string, int> psi;
typedef pair <string, string> pss;
typedef pair <double, int> pdi;
const double PI = acos(-1.0);
const double EI = exp(1.0);
const double eps = 1e-8;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fll;
const int maxn = (int)4e3 + 10;
const int MAXN = (int)1e2 + 10;
const int MOD = (int)1e9 + 7;
int readint()
{
int num; scanf("%d", &num);
return num - 1;
}
struct node
{
pii G[4];
int step, value, vis;
bool operator == (const node& r)const
{
for (int i = 0; i < 8; i++)
if (r.G[i] != G[i])
return false;
return true;
}
void tran()
{
value = 0;
sort(G, G + 4, [](pii a, pii b) { if (a.fi == b.fi) return a.se < b.se; else return a.fi < b.fi; });
for (int i = 0; i < 4; i++) value = value * 10 + G[i].fi, value = value * 10 + G[i].se;
}
void read(int l, int r)
{
for (int i = l; i < r; i++) { G[i].fi = readint(); G[i].se = readint();}
step = 0; tran();
}
}st, tar;
void init()
{
st.G[0].se = readint(); st.G[0].fi--;
st.read(1, 4); tar.read(0, 4);
st.vis = 0; tar.vis = 1;
}
int Move[2][4][2] =
{
-1, 0,
1, 0,
0,-1,
0, 1,
-2, 0,
2, 0,
0,-2,
0, 2,
};
bool ok(int x, int y)
{
if (x < 0 || x >= 8 || y < 0 || y >= 8)
return false;
return true;
}
void bfs()
{
if (st == tar)
{
puts("YES");
return;
}
queue <node> q[2]; q[0].push(st); q[1].push(tar);
map <int, pii> mp[2]; mp[0][st.value] = pii(1, 0); mp[1][tar.value] = pii(1, 0);
while (!q[0].empty() && !q[1].empty())
{
node u;
if (q[0].size() < q[1].size()) { u = q[0].front(); q[0].pop(); }
else { u = q[1].front(); q[1].pop(); }
if (u.step >= 8) continue;
map <pii, int> visit;
for (int i = 0; i < 4; i++)
visit[u.G[i]] = 1;
for (int i = 0; i < 4; i++)
{
int x = u.G[i].fi, y = u.G[i].se;
for (int j = 0; j < 4; j++)
{
int nx = x + Move[0][j][0];
int ny = y + Move[0][j][1];
if (ok(nx, ny))
{
if (visit[pii(nx, ny)])
{
nx = x + Move[1][j][0];
ny = y + Move[1][j][1];
if (ok(nx, ny) && visit[pii(nx, ny)] == 0)
{
node v = u;
swap(v.G[i].fi, nx); swap(v.G[i].se, ny);
v.step++; v.tran();
if (mp[v.vis][v.value].fi == 0)
{
mp[v.vis][v.value] = pii(1, v.step);
pii tmp = mp[v.vis ^ 1][v.value];
if (tmp.fi == 1 && tmp.se + v.step <= 8)
{
puts("YES");
return;
}
q[v.vis].push(v);
}
}
}
else
{
node v = u;
swap(v.G[i].fi, nx); swap(v.G[i].se, ny);
v.step++; v.tran();
if (mp[v.vis][v.value].fi == 0)
{
mp[v.vis][v.value] = pii(1, v.step);
pii tmp = mp[v.vis ^ 1][v.value];
if (tmp.fi == 1 && tmp.se + v.step <= 8)
{
puts("YES");
return;
}
q[v.vis].push(v);
}
}
}
}
}
}
puts("NO");
return;
}
int main()
{
while (scanf("%d", &st.G[0].fi) != EOF)
{
init(); bfs();
}
}
ZOJ - 1505 Solitaire 【双向BFS】的更多相关文章
- Hdu1401-Solitaire(双向bfs)
Solitaire is a game played on a chessboard 8x8. The rows and columns of the chessboard are numbered ...
- HDU 1401 Solitaire 双向DFS
HDU 1401 Solitaire 双向DFS 题意 给定一个\(8*8\)的棋盘,棋盘上有4个棋子.每一步操作可以把任意一个棋子移动到它周围四个方向上的空格子上,或者可以跳过它四个方向上的棋子(就 ...
- POJ1915Knight Moves(单向BFS + 双向BFS)
题目链接 单向bfs就是水题 #include <iostream> #include <cstring> #include <cstdio> #include & ...
- HDU 3085 Nightmare II 双向bfs 难度:2
http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...
- POJ 3170 Knights of Ni (暴力,双向BFS)
题意:一个人要从2先走到4再走到3,计算最少路径. 析:其实这个题很水的,就是要注意,在没有到4之前是不能经过3的,一点要注意.其他的就比较简单了,就是一个双向BFS,先从2搜到4,再从3到搜到4, ...
- [转] 搜索之双向BFS
转自:http://www.cppblog.com/Yuan/archive/2011/02/23/140553.aspx 如果目标也已知的话,用双向BFS能很大程度上提高速度. 单向时,是 b^le ...
- 双向BFS
转自“Yuan” 如果目标也已知的话,用双向BFS能很大提高速度 单向时,是 b^len的扩展. 双向的话,2*b^(len/2) 快了很多,特别是分支因子b较大时 至于实现上,网上有些做法是用两个 ...
- HDU 3085 Nightmare Ⅱ (双向BFS)
Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 3085 Nightmare Ⅱ 双向BFS
题意:很好理解,然后注意几点,男的可以一秒走三步,也就是三步以内的都可以,鬼可以穿墙,但是人不可以,鬼是一次走两步 分析:我刚开始男女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是 ...
随机推荐
- .mata. _root_ (转)
HRegionServer 里面存放了很多的HRegion,而且每一个HRegion都有一个唯一标识(表名+开始主键+唯一ID),这个唯一标识符在每一个HRegion中都有存储. .mata.表存的数 ...
- ”ftp使用dos命令“
ftp不能使用dos命令,ftp有专用的命令. 在批处理文件中,如果用到dos命令获取信息(比如:系统日期),将用获取的信息,输出到ftp脚本文件中,然后执行ftp脚本文件. set yyyy=%DA ...
- ajax个人学习笔记
1. function createXHR(){ if(typeof XMLHttpRequest != 'undefined'){ return new XMLHttpRequest(); }els ...
- atom无法安装插件的解决方法
atom通过setting中无法下载插件,通过apm也无法下载插件,可能是网络.config配置的问题,不好解决. 下面的方法全手动,基本属于万金油方法: 1,在atom的setting页面中点击op ...
- php函数总结(闭包函数,匿名函数)
php函数总结 1.普通函数 2.变量函数 function myfun($a) { echo $a; } $b = "myfun"; $b("test"); ...
- SpringBoot集成actuator模块的基本使用
© 版权声明:本文为博主原创文章,转载请注明出处 1. 版本 SpringBoot:2.0.0.RELEASE 2. 集成 SpringBoot集成actuator模块非常简单,只需要引入actuat ...
- YUV420视频上面添加字幕
1.source_codemain.c中实现了函数draw_Font_Func(),这个函数可以直接移植到C程序中使用.zimo.h里面放的是字模转码后的数据. 2.data_yuv测试用的yuv42 ...
- Arcgis:什么是栅格数据类型
栅格数据单元大小 栅格所表示的内容的详细程度(要素现象)通常取决于栅格的单元(像素)大小或空间分辨率. 单元必须足够小,这样才可以捕获到所需的详细信息: 而单元又必须足够大,这样才可以提高计算机存储和 ...
- es6/es7 对象数组的合并拷贝
方法一: let o1 = { a: 1, b: 2, c: 3 }; let o2 = {...o1, d: 4}; // o2 = { a: 1, b: 2, c: 3, d: 4 } let a ...
- hdu 4112 Break the Chocolate(乱搞题)
题意:要把一块n*m*k的巧克力分成1*1*1的单元,有两种操作方式:1,用手掰(假设力量无穷大),每次拿起一块,掰成两块小的:2,用刀切(假设刀无限长),可以把多块摆在一起,同时切开.问两种方式各需 ...