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:求最少的步骤.使得 ...
随机推荐
- [转] linux之sed用法
sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法sed命令行格式为: sed ...
- android之旅——开始
1.文件的读取 io流读取文件,并且显示 package com.helloword; import java.io.BufferedReader; import java.io.File; impo ...
- (转)PHP的ereg()与eregi()的不同及相同点。对比
ereg() 字符串比对解析. 语法: int ereg(string pattern, string string, array [regs]); 返回值: 整数/数组 函数种类: 资料处理 内容说 ...
- scrolView
禁止UIScrollView垂直方向滚动,只允许水平方向滚动 scrollview.contentSize = CGSizeMake(长度, 0); 禁止UIScrollView水平方向滚动,只允许 ...
- Swift - 04 - 浮点型
import UIKit var str = "Hello, playground" // 显式定义浮点型常量 let PI:Float = 3.141592612312312 l ...
- 深入理解offsetTop与offsetLeft
做为走上前端不归路的我,以前只是认为offsetTop是元素的左边框至包含元素offsetParent的左内边框之间的像素距离,同理offsetRight是相对于上内边框.那么问题来了,包含元素off ...
- Hive学习之一 《Hive的介绍和安装》
一.什么是Hive Hive是建立在 Hadoop 上的数据仓库基础构架.它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储.查询和分析存储在 Hadoop 中的大规模数据 ...
- 如何让Hadoop运行得更快一些
在数据处理方面,我们发现数据输入速度一般要比的数据处理速度快很多,这种现象在大多数据领域尤为明显.随着数据不断膨胀,相应的响应时间自然要有所增加,数据处理的复杂度也在不断提高.作为一个开发者,我们自然 ...
- id class
id 选择器可以为标有特定 id 的 HTML 元素指定特定的样式. HTML元素以id属性来设置id选择器,CSS 中 id 选择器以 "#" 来定义. 以下的样式规则应用于元素 ...
- 更快的使用你的键盘:AUTOHOTKEY
本文适合于:每天用电脑工作学习的朋友.游戏发烧手指又不灵敏的朋友.希望提高自己使用电脑效率的朋友. 本文将将告诉你AutoHotkey能做什么,并会一步一步地教会你轻易地使用它,但不会教你更多Auto ...