传送门

广搜

4*4 的方阵只有 0 和 1

显然可以状态压缩

(如样例的开始状态压缩后就是1111000011100010)

为了加快速度用了双向广搜(顺便学了一下双向广搜)

双向广搜顾名思义

就是从起点和终点两个方向广搜

每次选择扩展步数少的扩展一层

然后一旦一个状态被两边都找到了

那就把两边的步数加一下,就是答案了

然后要注意位运算的细节

具体实现看代码吧

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
struct node
{
int p,stp;
};//广搜的队列,p表示状态,stp表示当前走了几步
queue <node> q[];
bool pd[][];//记忆化,pd[i][]为到i状态需要的最少步数
int ans,st,lst;
inline void add(int k,int p,int stp)
//尝试把状态p加入队列
{
if(pd[p][k^]||(p==st&&k)||(p==lst&&k==))//如果另一边已经找过了或者到了另一边的起点
//因为在起点和终点的pd为0 所以要特判一下
{
ans=stp+pd[p][k^];//更新ans
return;//直接返回
}
if(pd[p][k]||p==st||p==lst) return;//如果找过了或者回到开始点,直接返回 //否则
pd[p][k]=stp;//更新pd
node t; t.p=p; t.stp=stp;
q[k].push(t);//加入队列
}
inline void bfs()
{
int k= q[].size()<q[].size();//确定要从哪一边扩展
int now=q[k].front().stp;
while(!q[k].empty())
{
node t=q[k].front();
if(t.stp>now||ans) break;//保证一次只扩展一层
q[k].pop();//(细节)要先判断再弹出
for(int i=;i>=;i--)//向左移动
{
if(i%==) continue;//注意如果在边界就不能动
if( !(t.p& (<<i) ) || t.p& ( <<(i+) ) ) continue;//判断
add(k, t.p^ (<<i) ^ ( <<(i+) ), t.stp+);//直接异或一波得到下一步的状态
}
for(int i=;i>=;i--)//向右
{
if(i%==) continue;//同样判断
if( !(t.p& (<<i) ) || t.p& (<<(i-) ) ) continue;
add(k, t.p^ (<<i) ^ ( <<(i-) ), t.stp+);
}//同上
for(int i=;i>=;i--)//向上,注意i的范围
{
if( !(t.p& (<<i) ) || t.p& (<<(i+) ) ) continue;
add(k, t.p^ (<<i) ^ ( <<(i+) ), t.stp+);
}//同上
for(int i=;i>=;i--)//向上,同样注意i
{
if( !(t.p& (<<i) ) || t.p& (<<(i-) ) ) continue;
add(k, t.p^ (<<i) ^ ( <<(i-) ), t.stp+);
}//同上
}
}
int main()
{
char ss[]; memset(ss,,sizeof(ss));
for(int i=;i<;i++)
{
cin>>ss;
for(int j=;j<;j++)
st+=( (ss[j]-'')<<(-i*-j) );
}//读入状态
node t; t.p=st; t.stp=;
q[].push(t);//开始状态压入队列 for(int i=;i<;i++)
{
cin>>ss;
for(int j=;j<;j++)
lst+=( (ss[j]-'')<<(-i*-j) );
}
t.p=lst; q[].push(t);//同上 if(st==lst)//特判一波起点和终点状态相同的情况
{
cout<<;
return ;
} while(!ans)
bfs();//广搜找ans
cout<<ans;
}

P4289 [HAOI2008]移动玩具的更多相关文章

  1. P4289 [HAOI2008]移动玩具(bfs)

    P4289 [HAOI2008]移动玩具 双向bfs+状态压缩+记忆化搜索 双向bfs用于对bfs的优化,每次找到可扩展节点少的一边进行一次bfs,找到的第一个互相接触的点即为最短路径 矩阵范围仅4* ...

  2. luogu P4289 [HAOI2008]移动玩具

    传送门 这道题可以二进制记录状态搜索 也可以做以下考虑 若一个棋子要移动到另一个位置上去,则步数为两点的曼哈顿距离(横坐标差的绝对值+纵坐标差的绝对值),因为假设路径上有其他的棋子,可以通过移动其他棋 ...

  3. P4289 【一本通提高篇广搜的优化技巧】[HAOI2008]移动玩具

    [HAOI2008]移动玩具 题目描述 在一个 4 × 4 4\times4 4×4 的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动时只能将玩具向上下左右四个方 ...

  4. bzoj 1054: [HAOI2008]移动玩具 bfs

    1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MB[Submit][Status][Discuss] Description 在 ...

  5. bzoj1054: [HAOI2008]移动玩具

    hash+bfs:要注意特殊情况.(似乎连sort.lower_bound都不用数据小直接判重了... #include<cstdio> #include<cstring> # ...

  6. BZOJ 1054 [HAOI2008]移动玩具

    1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1388  Solved: 764[Submit][Statu ...

  7. 1054: [HAOI2008]移动玩具

    1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1272  Solved: 690[Submit][Statu ...

  8. 【BZOJ1054】[HAOI2008]移动玩具

    [BZOJ1054][HAOI2008]移动玩具 题面 bzoj 洛谷 题解 太\(sb\)了,不想写了,直接点开洛谷题面单击右边蓝色按钮题解即可

  9. 【BZOJ1054】[HAOI2008]移动玩具 BFS

    [BZOJ1054][HAOI2008]移动玩具 Description 在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动 时只能将玩具向上下左右四个 ...

随机推荐

  1. JS写一个简单的程序,输入两个整数,打印这两个数的和,差,积,余数

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. python的print字符串的输出

    字符串的输出使用print语句,在每个语句的输出的时候我们使用' '和" "来包含字符串比如: 如果有多个字符串的话呢我们需要用”,“来进行连接: 我们不仅可以使用字符来进行输出时 ...

  3. Android上 dip、dp、px、sp等单位说明

    dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA.HVGA和QVGA 推荐使用这个,不依赖像素. ...

  4. 并发之AtomicInteger

    并发之AtomicInteger 1 java.util.concurrent.atomic概要     在java.util.concurrent.atomic包下存在着18个类,其中Integer ...

  5. [luogu3385]dfs_spfa判负环模板

    解题关键:模板保存. 判负环不需要memset dis数组,因为已经更新过得d数组一定小于0,如果当前点可以更新d,说明d更小,有可能继续扩大负环,所以继续更新:如果比d[v]大,则不可能继续更新负环 ...

  6. 深、浅copy

    深.浅copy多用于列表 浅copy:第一层中不变的数据是独立的,可变类型元素指向同一块内存地址 l1 = [1,2,3,["a","b"]] l2 = l1. ...

  7. 炫酷实用的CSS3代码垂直手风琴菜单

    今天在微博上看到别人分享的代码,自己拿来自己保存着. 代码效果如下: 下面是源码: index.html <!DOCTYPE html> <html > <head> ...

  8. Loading Large Bitmaps Efficiently

    有效地加载大位图文件-Loading Large Bitmaps Efficiently 图像有各种不同的形状和大小.在许多情况下,他们往往比一个典型应用程序的用户界面(UI)所需要的资源更大.例如, ...

  9. C++笔记--名字空间和异常

    名字空间 成员函数可以在名字空间的定义里去声明,然后再去采用一种定义方式例如:namespace__name::member_name的方式去定义这个成员函数 namespace parser{ do ...

  10. OpenStack部署的简单模型

    记录下看到的openstack部署的简单模型,方便自己以后定位问题 规划网络部署节点为一个controller节点(包含网络节点),两个compute节点.controller节点有3个网卡,分别为e ...