HDU_1401——分步双向BFS,八进制位运算压缩,map存放hash
There are four identical pieces on the board. In one move it is allowed to:
> move a piece to an empty neighboring field (up, down, left or right),
> jump over one neighboring piece to an empty field (up, down, left or right). There are 4 moves allowed for each piece in the configuration shown above. As an example let's consider a piece placed in the row 4, column 4. It can be moved one row up, two rows down, one column left or two columns right.
Write a program that:
> reads two chessboard configurations from the standard input,
> verifies whether the second one is reachable from the first one in at most 8 moves,
> writes the result to the standard output.
2 4 3 3 3 6 4 6
#include <cstdio>
#include <map>
#include <queue>
#include <algorithm>
using namespace std; struct point
{
int x,y;
bool check()
{
if(x>= && x<= && y>= && y<=)
{
return true;
}
return false;
}
};
struct chess
{
point pos[];
int step;
bool check(int j)
{
for(int i=;i<;i++)
{
if(i!=j && pos[j].x==pos[i].x && pos[j].y==pos[i].y)
return true;
}
return false;
}
}start,end; const int dir[][]={,,,-,,,-,};
map<int,int>mapint;
map<int,int>::iterator it; /*
对棋盘状态进行进制压缩处理,棋子坐标(x,y):0~7
变成二进制:000~111,一共有4个棋子,所以一共有(x,y)坐标4个
把棋型压缩成二进制形式,共24位。因为棋子都是相同的
所以每次压缩前,都要对棋子坐标(x,y)进行排序,
否则棋型相同棋子序号不同时,会出现不同的压缩状态
*/
bool cmp(point a,point b) //按x升序排序,如果x相等就按y升序排序
{
return a.x!=b.x ? a.x<b.x : a.y<b.y; //>降序,<升序
}
int get_hash(point *temp)
{
int res = ;
sort(temp,temp+,cmp);
for(int i=;i<;i++) //枚举棋子
{
res |= ( temp[i].x<<(*i) );
res |= ( temp[i].y<<(*i+) );
}
return res;
} bool BFS(int flag,chess temp) //flag=1:从起点开始搜索,flag=2:终点开始
{
/*
if(flag == 2) //当从终点开始搜索时,先在存储起点搜索压缩状态的map容器中查找,是否已经到到达过终点
{
it = mapint.find(get_hash(temp.pos));
if(it != mapint.end())
{
return true;
}
}
mapint[get_hash(temp.pos)] = flag;
*/
queue<chess>que;
que.push(temp); while(!que.empty())
{
temp = que.front();
que.pop();
if(temp.step >= ) //搜索步数不超过4步
{
continue;
}
for(int i=;i<;i++) //枚举方向
{
for(int j=;j<;j++) //枚举棋子
{
chess next = temp;
next.step++;
next.pos[j].x += dir[i][];
next.pos[j].y += dir[i][]; if(!next.pos[j].check()) //判断棋子是否在棋盘内
{
continue;
}
if(next.check(j)) //判断棋子j是否和其他棋子重叠
{
next.pos[j].x += dir[i][]; //重叠之后再前进一步
next.pos[j].y += dir[i][];
if(!next.pos[j].check()) //再次检查是否越界
{
continue;
}
if(next.check(j)) //再次检查是否重叠
{
continue;
}
} int hash = get_hash(next.pos); //获得一种新的状态
it = mapint.find(hash); //在容器中搜索这个新状态 if(flag == ) //从起点开始的搜索
{ if(it == mapint.end()) //没找到,记录压缩状态,推入队列
{
mapint[hash] = flag;
que.push(next);
} else if(it -> second == ) //找到的是终点搜索过来的状态
{
return true;
} }
else //从终点开始的搜索
{
if(it == mapint.end()) //没找到,推入队列
{
que.push(next); //不需要再生成压缩状态并记录了
}
else if(it -> second == ) //找到的是起点搜索过来的状态
{
return true;
}
}
}
}
}
return false;
} int main()
{
while(~scanf("%d%d",&start.pos[].x,&start.pos[].y))
{
for(int i=;i<;i++)
{
scanf("%d%d",&start.pos[i].x,&start.pos[i].y);
}
for(int i=;i<;i++)
{
scanf("%d%d",&end.pos[i].x,&end.pos[i].y);
}
for(int i=;i<;i++) //把棋盘坐标由1~8转化成0~7,方便进制压缩
{
start.pos[i].x--; start.pos[i].y--;
end.pos[i].x--; end.pos[i].y--;
}
start.step = end.step = ; mapint[get_hash(start.pos)] = ; //搜索之前先把初始压缩状态放入map容器,防止起点和终点一样的情况
mapint[get_hash(end.pos)] = ; if(BFS(,start) || BFS(,end))
{
printf("YES\n");
}
else
{
printf("NO\n");
} mapint.clear(); //狗日的一定要记住,容器什么的每次要清空
}
return ;
}
HDU_1401——分步双向BFS,八进制位运算压缩,map存放hash的更多相关文章
- HDU_1401——同步双向BFS,八进制位运算压缩,map存放hash
这个速度比分步快一点,内存占的稍微多一点 Problem Description Solitaire is a game played on a chessboard 8x8. The rows an ...
- HDU_1401——分步双向BFS,八进制乘权值压缩,map存放hash
Problem Description Solitaire is a game played on a chessboard 8x8. The rows and columns of the ches ...
- HDU 3605 Escape (网络流,最大流,位运算压缩)
HDU 3605 Escape (网络流,最大流,位运算压缩) Description 2012 If this is the end of the world how to do? I do not ...
- uva 1601 poj 3523 Morning after holloween 万圣节后的早晨 (经典搜索,双向bfs+预处理优化+状态压缩位运算)
这题数据大容易TLE 优化:预处理, 可以先枚举出5^3的状态然后判断合不合法,但是由于题目说了有很多墙壁,实际上没有那么多要转移的状态那么可以把底图抽出来,然后3个ghost在上面跑到时候就不必判断 ...
- poj2965(位运算压缩+bfs+记忆路径)
题意:有个4*4的开关,里面有着16个小开关 -+-- ---- ---- '+'表示开关是关着的,'-'表示开关是开着的,只有所有的开关全被打开,总开关才会被打开.现在有一种操作,只要改变某个开关, ...
- poj1753(位运算压缩状态+bfs)
题意:有个4*4的棋盘,上面摆着黑棋和白旗,b代表黑棋,w代表白棋,现在有一种操作,如果你想要改变某一个棋子的颜色,那么它周围(前后左右)棋子的颜色都会被改变(白变成黑,黑变成白),问你将所有棋子变成 ...
- 【BFS】【位运算】解药还是毒药
[codevs2594]解药还是毒药 Description Smart研制出对付各种症状的解药,可是他一个不小心,每种药都小小地配错了一点原料,所以这些药都有可能在治愈某些病症的同时又使人患上某些别 ...
- HDU5627--Clarke and MST (bfs+位运算)
http://www.cnblogs.com/wenruo/p/5188495.html Clarke and MST Time Limit: 2000/1000 MS (Java/Others) M ...
- POJ 1753 bfs+位运算
T_T ++运算符和+1不一样.(i+1)%4 忘带小括号了.bfs函数是bool 型,忘记返回false时的情况了.噢....debug快哭了...... DESCRIPTION:求最少的步骤.使得 ...
随机推荐
- iOS 短信验证码倒计时按钮的实现
验证码倒计时按钮的应用是非常普遍的,本文介绍了IOS实现验证码倒计时功能,点击获取验证码,进入时间倒计时,感兴趣的小伙伴们可以参考一下: 实现思路: 创建按钮,添加点击方法: 用NSTimer定时器, ...
- Python之路,Day13-----暂无正在更新中
Python之路,Day13-----暂无正在更新中
- servlet 配置到服务器
最近写了个安卓项目,服务端用的servlet.因为第一次写java项目,写完如何发布不是太清除,于是把这回经理写出来,一来做个记录,二来也给和我同样经历的朋友一点启示. 首先配置你的java主机和你的 ...
- ASP.NET-FineUI开发实践-12
1.网上找到了行合并的示例,extjs写的,我把它挪过来改了下,FineUI也能用,就是只能放着看,选择和编辑行扩展列没有测试,放出来大家看着用吧. <script> F.ready(fu ...
- HTML简要内容
1. html基础 html是用来制作网页的标记语言,不需编译,直接由浏览器执行.大小写不敏感,推荐使用小写.html文件必须使用html或htm为文件名后缀. html主体结构: (1)DTD头: ...
- 13个简单有用的android开发代码
1:查看是否有存储卡插入 String status=Environment.getExternalStorageState(); if(status.equals(Enviroment.MEDIA_ ...
- C++中L和_T()之区别(转)
C++中L和_T()之区别 分类: C/C++2011-01-12 11:45 2878人阅读 评论(1) 收藏 举报 c++编译器apic 字符串前面加L表示该字符串是Unicode字符串._T是一 ...
- centos 用户切换
在系统的/etc/.bash_profile中已经配置了各种环境变量. 用账户a登陆,ldd xxx.so查看一切链接正常. 用账户root登陆,ldd xxx.so查看一切链接正常. 用账户a登陆, ...
- jQuery操作cookie
验证jquery的cookie插件时才知道原先文件一直在桌面上放着执行发现没有效果,文件必须放在web服务器下面执行才会生效,晕菜! $.cookie(name,value,{expires: 7,p ...
- JS判断鼠标从哪个方向进入DIV容器
写的不够高大上 , 不要介意哦... Js: //进去 $(".flash").bind("mouseenter",function(e){ /** the w ...