Hdu1401-Solitaire(双向bfs)
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.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int mod=;
const int maxn=;
int dx[]={-,,,},dy[]={,-,,};
bool in(int x,int y){ return x>=&&x<=&&y>=&&y<=; }
struct point //球的坐标
{
int x,y;
point(int x=,int y=):x(x),y(y){}
bool operator < (const point& t) const
{
if(x!=t.x) return x<t.x;
return y<t.y;
}
};
struct node
{
point p[]; //每个节点保存4个球的坐标,并且是排好序的
}nod[][maxn]; //开二维用于双向搜
struct Hash
{
int v,k,nid,next; //保存哈希值,0或1,下标,next指针
}ha[mod+maxn];
int f[],r[],hash_id; //队首队尾指针
bool Same(int k1,int a,int k2,int b) //判断两个结构体是否完全相同
{
for(int i=;i<;i++)
{
if(nod[k1][a].p[i].x!=nod[k2][b].p[i].x) return false;
if(nod[k1][a].p[i].y!=nod[k2][b].p[i].y) return false;
}
return true;
}
int GetHash(point p[]) //得到哈希值
{
int ret=,k=;
for(int i=;i<;i++)
{
ret+=p[i].x*k; k*=; //k是系数
ret+=p[i].y*k; k*=;
}
return ret;
}
int Insert_Hash(int v,int k,int nid) //插入
{
int a=v%mod;
int p=ha[a].next;
while(p!=-)
{
if(ha[p].v==v&&Same(ha[p].k,ha[p].nid,k,nid)) return ha[p].k==k?:; //有相同的状态,k值相同返回0,不同返回1
p=ha[p].next;
}
p=++hash_id;
ha[p].v=v; ha[p].k=k; ha[p].nid=nid; //增加新的节点
ha[p].next=ha[a].next; ha[a].next=p;
return -;
}
bool Has(node& t,int x,int y)
{
for(int i=;i<;i++) if(t.p[i].x==x&&t.p[i].y==y) return true; //此处是球
return false;
}
bool AddNode(node& t,int i,int j,int k)
{
int x=t.p[i].x;
int y=t.p[i].y;
int nx=x+dx[j];
int ny=y+dy[j];
if(!in(nx,ny)) return false; //出界
if(Has(t,nx,ny)) nx+=dx[j],ny+=dy[j]; //有球
if(!in(nx,ny)) return false; //出界
if(Has(t,nx,ny)) return false; //还有球
node& tt=nod[k][r[k]];
tt=t;
tt.p[i].x=nx; tt.p[i].y=ny;
sort(tt.p,tt.p+); //排序
int a=Insert_Hash(GetHash(tt.p),k,r[k]);
if(a==) return true; //找到解
else if(a==-) r[k]++; //增加新节点
return false;
}
bool bfs(int k)
{
int en=r[k];
while(f[k]<en)
{
node& t=nod[k][f[k]++];
for(int i=;i<;i++) //4个球4个方向
for(int j=;j<;j++) if(AddNode(t,i,j,k)) return true;
}
return false;
}
bool solve()
{
if(Same(,,,)) return true; //相同
int step=;
f[]=f[]=; r[]=r[]=;
for(int i=;i<mod;i++) ha[i].next=-;
hash_id=mod-;
Insert_Hash(GetHash(nod[][].p),,);
Insert_Hash(GetHash(nod[][].p),,);
while(f[]<r[]||f[]<r[])
{
if(step>=) return false;
step++;
if(bfs()) return true;
if(bfs()) return true;
}
return false;
}
int main()
{
int x,y;
while(scanf("%d%d",&x,&y)!=EOF)
{
nod[][].p[]=point(x,y);
for(int i=;i<;i++)
{
scanf("%d%d",&x,&y);
nod[][].p[i]=point(x,y);
}
for(int i=;i<;i++)
{
scanf("%d%d",&x,&y);
nod[][].p[i]=point(x,y);
}
sort(nod[][].p,nod[][].p+);
sort(nod[][].p,nod[][].p+);
if(solve()) printf("YES\n");
else printf("NO\n");
}
return ;
}
Hdu1401-Solitaire(双向bfs)的更多相关文章
- HDU1401(双向BFS)
题意:http://acm.hdu.edu.cn/showproblem.php?pid=1401 给你8*8的棋盘和4个棋子初始位置.最终位置,问你能否在8次操作后达到该状态. 思路: 双向BFS, ...
- HDU 1401 Solitaire 双向DFS
HDU 1401 Solitaire 双向DFS 题意 给定一个\(8*8\)的棋盘,棋盘上有4个棋子.每一步操作可以把任意一个棋子移动到它周围四个方向上的空格子上,或者可以跳过它四个方向上的棋子(就 ...
- POJ1915Knight Moves(单向BFS + 双向BFS)
题目链接 单向bfs就是水题 #include <iostream> #include <cstring> #include <cstdio> #include & ...
- HDU 3085 Nightmare II 双向bfs 难度:2
http://acm.hdu.edu.cn/showproblem.php?pid=3085 出的很好的双向bfs,卡时间,普通的bfs会超时 题意方面: 1. 可停留 2. ghost无视墙壁 3. ...
- POJ 3170 Knights of Ni (暴力,双向BFS)
题意:一个人要从2先走到4再走到3,计算最少路径. 析:其实这个题很水的,就是要注意,在没有到4之前是不能经过3的,一点要注意.其他的就比较简单了,就是一个双向BFS,先从2搜到4,再从3到搜到4, ...
- [转] 搜索之双向BFS
转自:http://www.cppblog.com/Yuan/archive/2011/02/23/140553.aspx 如果目标也已知的话,用双向BFS能很大程度上提高速度. 单向时,是 b^le ...
- 双向BFS
转自“Yuan” 如果目标也已知的话,用双向BFS能很大提高速度 单向时,是 b^len的扩展. 双向的话,2*b^(len/2) 快了很多,特别是分支因子b较大时 至于实现上,网上有些做法是用两个 ...
- HDU 3085 Nightmare Ⅱ (双向BFS)
Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 3085 Nightmare Ⅱ 双向BFS
题意:很好理解,然后注意几点,男的可以一秒走三步,也就是三步以内的都可以,鬼可以穿墙,但是人不可以,鬼是一次走两步 分析:我刚开始男女,鬼BFS三遍,然后最后处理答案,严重超时,然后上网看题解,发现是 ...
随机推荐
- Day56
今天干啦啥呢 早上七点起来 天气冷了真起不来啊 再坚持坚持就好了 今天上午九点开始考数据库 我去 大学四年第一次感觉到这样的爽 作弊的爽啊 也没有完全的作弊啦 是开卷考试,反正做的很顺利了. 我和胡 ...
- NUnit - 使用感受
Nunit使用 最近项目开始大量使用Nunit, 发现Nunit还是有很多好处的. 1. 测试驱动逻辑,这样可以尽最大可能减少“修改”引入的Bug. 如果你修改了一些东西,导致Case跑不过.请检查你 ...
- mysql 获取当前时间戳
mysql 获取当前时间为select now() 运行结果: 2012-09-05 17:24:15 mysql 获取当前时间戳为select unix_timestamp(now()) 运行结 ...
- Spring Ldap 的增删改查
package ldap.entity; /** * 本测试类person对象来自schema文件的core.schema文件 * objectClass为person,必填属性和可选属性也是根据该对 ...
- [Redux] React Todo List Example (Filtering Todos)
/** * A reducer for a single todo * @param state * @param action * @returns {*} */ const todo = ( st ...
- AngularJS移动开发中的坑汇总
使用AngualrJs开发移动App已经快半年了,逐渐积累了非常多AngularJS的问题,特别是对于用惯了Jquery的开发人员,转到AngularJS还是须要克服非常多问题的.不像Jquery那样 ...
- iOS程序的加载过程
1.执行main函数2.执行UIApplicationMain函数1> 创建一个UIApplication对象(UIApplication是整个程序的象征)一个应用只有一个application ...
- 命令行下如何安装VMware Tools并与windows资料共享
安装VMware Tools: 选择菜单栏“虚拟机”——“安装VMware tools” ,等待系统自动更换ISO光盘 mount /dev/cdrom /mntcd /mnttar zxvf VMw ...
- 什么是系统平均负载(Load average)
一.什么是系统平均负载(Load average)? 在Linux系统中,uptime.w.top等命令都会有系统平均负载load average的输出,那么什么是系统平均负载呢? Load Aver ...
- 获取sqlserver数据库中所有库、表、字段名的方法
获取sqlserver数据库中所有库.表.字段名的方法 2009年03月12日 星期四 下午 12:51 1.获取所有数据库名: SELECT Name FROM Master..SysDatabas ...