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:求最少的步骤.使得 ...
随机推荐
- 《Android群英传》读书笔记 (2) 第三章 控件架构与自定义控件详解 + 第四章 ListView使用技巧 + 第五章 Scroll分析
第三章 Android控件架构与自定义控件详解 1.Android控件架构下图是UI界面架构图,每个Activity都有一个Window对象,通常是由PhoneWindow类来实现的.PhoneWin ...
- maven 启动忽略test
两种方法 1,--命令 mvn install -Dmaven.test.skip=true 2.pom.xml 文件 在tomcat 下面的pom.xml 文件里面加上如下 <!-- ski ...
- 优雅退出 Android 应用程序的 6 种方式
我们先来看看几种常见的退出方法(不优雅的方式) 一.容器式 建立一个全局容器,把所有的Activity存储起来,退出时循环遍历finish所有Activity import java.util.Arr ...
- Linux编程之定制带级别的log
我的开发组长曾经说过这么一段话"一个优秀的程序员不在于他写代码有多快,也不在于他能不能实现这个模块的功能,要实现业务实现功能谁不会啊,重要的是他的解决能力,也就说当程序出现错误时你能不能够快 ...
- codevs 1281 Xn数列 (矩阵乘法)
/* 再来个题练练手 scanf longlong 有bug....... */ #include<cstdio> #include<iostream> #include< ...
- js正则表达式验证大全
/判断输入内容是否为空 function IsNull(){ var str = document.getElementById('str').value.trim(); ...
- 生成PDF并下载。
例子是生成一个pdf格式的证书: //创建Document Document document = null; //为该Document创建一个Writer实例 PdfWriter writer = ...
- (转)PHP ob_start() 函数介绍
php ob_start 与 ob_end_flush() 是 php 的缓冲输出函数. ob_start([string output_callback])- 打开输出缓冲区,所有的输出信息不在直接 ...
- android6.0源码分析之Camera API2.0下的Capture流程分析
前面对Camera2的初始化以及预览的相关流程进行了详细分析,本文将会对Camera2的capture(拍照)流程进行分析. 前面分析preview的时候,当预览成功后,会使能ShutterButto ...
- HTTP简单理解
自己最近正在看 <Java Web 整合开发实战>这本书, 看到HTTP协议,感觉写的挺明白了,就把书中内容总结了下,记录在此. 超文本传输协议(HyperText Transfer Pr ...