HDU 3900 Unblock Me
题目:Unblock Me
链接:Here
题意:一个游戏,看图就基本知道题意了,特殊的是:1. 方块长度为3或2,宽度固定是1。2. 地图大小固定是6*6,从0开始。 3. 出口固定在(6,2)。4. 每一步只能移动一个方块,但可以移动多个单位。5. 必定有解。求红色方块从出口离开的最小步骤数。

思路:
刚开始老老实实的用IDA*做,毫不犹豫的超时,样例都跑不动,剪枝也剪不了,大概知道要状态压缩,具体点就实在想不出来了,百度的题解,感觉刷新了我对状压的认识,用3位二进制表示一个方块的可变信息,然后组成一个LL型数。我写的IDA*,当时想加一个判断当前局面是否遇到过的剪枝,发现要想存状态并且快速找到很困难,现在如果用一个LL型数就可以表示局面,那就简单多了,set就可以解决。
可变信息是指在一个局面开始后会发生变化的信息,相对的不可变信息就比如某个竖立方块的列(在游戏过程中不会发生改变)、长度,因此用二维数组表示状态有很大的冗余,其实在游戏过程中竖立方块会发生变化的就只有行,而地图大小6,所以用3位二进制可以完整地保存,题目最多36/2=18个方块,所以一个LL型可以存下所有方块的信息。
接下来通过简单的位运算可以分离信息,剩下的就是bfs了,难点就在状态压缩,想到以后位置处理就简单了。
AC代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
#define N 20020
#define M 100010
#define Mod 1000000007
#define LL long long
#define INF 0x7fffffff
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
#define For(i,f_start,f_end) for(int i=f_start;i<f_end;i++)
#define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--)
#define Rep(i,f_end,f_start) for(int i=f_end;i>f_start;i--)
#define MT(x,i) memset(x,i,sizeof(x))
#define gcd(x,y) __gcd(x,y)
const double PI = acos(-); struct Node
{
bool type; //竖的 1 ,横的 0
int pos; //竖的记录行,横的记录列
int len; //长度
}v[]; int cal(LL s,int pos)
{
return (int)( ( s & (7LL << (pos * )) ) >> (pos * ) );
} int n,red; bool ok(LL s)
{
int rl = cal(s,red), rr = rl + v[red].len;
for(int i=;i<n;i++)
{
if(v[i].type) continue;
if(v[i].pos <= rr) continue;
int il = cal(s,i), ir = il + v[i].len;
if(ir < || il > ) continue;
return false;
}
return true;
} bool check(LL s,int pre)
{
int pl = cal(s,pre), pr = pl + v[pre].len;
for(int i=;i<n;i++)
{
if(i == pre) continue;
if(v[i].type == v[pre].type)
{
if(v[i].pos!=v[pre].pos) continue;
int il = cal(s,i), ir = il + v[i].len;
if(ir<pl || pr<il) continue;
}
else
{
int il = cal(s,i), ir = il + v[i].len;
if( pr < v[i].pos || pl > v[i].pos || il > v[pre].pos || ir < v[pre].pos) continue;
}
return false;
}
return true;
} void mov(LL &s,int pos,int x)
{
s &= ( ~( 7LL << (*pos) ) );
s |= ( (LL)x << (*pos) );
} set<LL> mp;
queue<pair<LL,int> > q;
int bfs(LL s)
{
if(ok(s)) return ;
while(q.size()) q.pop();
mp.clear();
q.push(make_pair(s,) );
while(q.size())
{
s = q.front().first;
int d = q.front().second + ;
q.pop();
for(int i=;i<n;i++)
{
int p = cal(s,i);
for(int j=;p-j>=;j++)
{
LL u = s;
mov(u,i,p-j);
if(check(u,i)==false) break;
if(mp.find(u)!=mp.end()) continue;
if(ok(u)) return d+;
mp.insert(u);
q.push(make_pair(u,d));
}
for(int j=;p+v[i].len+j<=;j++)
{
LL u = s;
mov(u,i,p+j);
if(check(u,i) == false) break;
if(mp.find(u)!=mp.end()) continue;
if(ok(u)) return d+;
mp.insert(u);
q.push(make_pair(u,d));
}
}
}
return -;
} int main()
{
while(~scanf("%d",&n))
{
LL s = ;
int x,y,x1,y1;
For(i,,n){
scanf("%*d%d%d%d%d",&x,&y,&x1,&y1);
if(x==x1){ // su
v[i].type = ;
v[i].pos = x;
v[i].len = y1-y;
s |= ( (LL)y << (i*) );
}
else
{
v[i].type = ;
v[i].pos = y;
v[i].len = x1-x;
s |= ( (LL)x << (i*) );
}
}
scanf("%d",&red);
printf("%d\n",bfs(s));
}
return ;
}
HDU 3900 Unblock Me的更多相关文章
- HDU 5643 King's Game 打表
King's Game 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5643 Description In order to remember hi ...
- HDOJ 2111. Saving HDU 贪心 结构体排序
Saving HDU Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 【HDU 3037】Saving Beans Lucas定理模板
http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...
- hdu 4859 海岸线 Bestcoder Round 1
http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...
- HDU 4569 Special equations(取模)
Special equations Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u S ...
- HDU 4006The kth great number(K大数 +小顶堆)
The kth great number Time Limit:1000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64 ...
- HDU 1796How many integers can you find(容斥原理)
How many integers can you find Time Limit:5000MS Memory Limit:32768KB 64bit IO Format:%I64d ...
- hdu 4481 Time travel(高斯求期望)(转)
(转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...
- HDU 3791二叉搜索树解题(解题报告)
1.题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3791 2.参考解题 http://blog.csdn.net/u013447865/articl ...
随机推荐
- 【Linux基础】VI命令模式下删除拷贝与粘贴
在VI命令模式下:y 表示拷贝, d 表示删除,p标识粘贴 1.删除 dw 表示删除从当前光标到光标所在单词结尾的内容. d0 表示删除从当前光标到光标所在行首的内容. d$ 表示删除从当前光标到光标 ...
- Announcing the Updated NGINX and NGINX Plus Plug‑In for New Relic (Version 2)
In March, 2013 we released the first version of the “nginx web server” plug‑in for New Relic monitor ...
- 忽略Git钩子
https://blog.csdn.net/alps1992/article/details/80464700 pre-commit GIT_DIR/hooks/pre-commit 这个钩子被 gi ...
- baidu.com跳转www.baidu.com
打开git bash,输入 curl baidu.com,收到返回 <html> <meta http-equiv="refresh" content=" ...
- Spring中事务配置以及事务不起作用可能出现的问题
前言:在Spring中可以通过对方法进行事务的配置,而不是像原来通过手动写代码的方式实现事务的操作,这在很大程度上减少了开发的难度,本文介绍Spring事务配置的两种方式:基于配置文件的方式和基于注解 ...
- SQLite也可能出现死锁
提到锁就不得不说到死锁的问题,而SQLite也可能出现死锁.下面举个例子:连接1:BEGIN (UNLOCKED)连接1:SELECT ... (SHARED)连接1:INSERT ... (RESE ...
- 在Ubuntu18.04上使用Anaconda
启动Anaconda Navigator 图形化界面 $ source ~/anaconda3/bin/activate root $ anaconda-navigator 查看目前的conda版本: ...
- Oracle的条件in中包含NULL时的处理
我们在写SQL时经常会用到in条件,如果in包含的值都是非NULL值,那么没有特殊的,但是如果in中的值包含null值(比如in后面跟一个子查询,子查询返回的结果有NULL值),Oracle又会怎么处 ...
- LOJ2014 SCOI2016 萌萌哒 并查集、ST表优化连边
传送门 一个朴素的做法就是暴力连边并查集,可是这是\(O(n^2)\)的.发现每一次连边可以看成两个区间覆盖,这两个区间之间一一对应地连边.可线段树对应的两个节点的size可能不同,这会导致" ...
- java多线程 - 处理并行任务
在多线程编程过程中,遇到这样的情况,主线程需要等待多个子线程的处理结果,才能继续运行下去.个人给这样的子线程任务取了个名字叫并行任务.对于这种任务,每次去编写代码加锁控制时序,觉得太麻烦,正好朋友提到 ...