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 ...
随机推荐
- 百度统计api获取数据
需求场景 想要了解每天多少人访问了网站,多少个新增用户,地域分布,点击了哪些页面,停留了多久,等等... 国内用的最多的就是百度统计吧,傻瓜式的注册然后插一段代码到项目里就行了. 最近也在自己的博客里 ...
- react中使用Ajax请求(axios,Fetch)
React本身只关注于界面, 并不包含发送ajax请求的代码,前端应用需要通过ajax请求与后台进行交互(json数据),可以使用集成第三方ajax库(或自己封装) 常用的ajax请求库 jQuery ...
- Linux平台上轻松安装与配置Domino
Linux平台上轻松安装与配置Domino Domino Server的编译安装过程中需要用到libstdc++-2.9和glibc-2.1.1(或者其更高的版本)两个编译模块,它们是Linux开发编 ...
- 《JAVA程序设计》_第一周学习总结
20175217吴一凡 <java程序设计> 第一周学习总结 虽然已经做好了心理准备,但第一周的学习任务着实让我忙了整整三天,还是挺充实的吧.寒假已经在自己的电脑上安装好了虚拟机,我就在我 ...
- C# Lambda 表达式学习之(四):动态构建类似于 c => c.Age == 2 || c.Age == 5 || c => c.Age == 17 等等一个或多个 OrElse 的表达式
可能你还感兴趣: 1. C# Lambda 表达式学习之(一):得到一个类的字段(Field)或属性(Property)名,强类型得到 2. C# Lambda 表达式学习之(二):LambdaExp ...
- 【转】AJAX发送 PUT和DELETE请求注意事项
jax使用restful服务发送put 和 delete 请求时直接传参会出现问题 一,采用POST + _method:delete/put + filter 的方法ajax发送put 和 de ...
- 使用pkg打包Node.js应用的方法步骤
Node.js应用不需要经过编译过程,可以直接把源代码拷贝到部署机上执行,确实比C++.Java这类编译型应用部署方便.然而,Node.js应用执行需要有运行环境,意味着你需要先在部署机器上安装Nod ...
- flask-sqlalchemy 一对一,一对多,多对多操作
先进行如下操作: from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy app=Flask(__name__) db= ...
- 给大家推荐一个C#下的Ribbon风格的Forms实现示例-含源码
C#下的Ribbon风格的Forms实现示例:源码下载地址
- num2cell
num2cell的作用是把数值数组转换为cell数组. 最基本的用法是把数值数组的每个元素作为cell数组的元素,得到一个和原数组维度完全相同的cell数组,例如 >> A=magic(3 ...