Eight
Eight
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043/http://acm.split.hdu.edu.cn/showproblem.php?pid=1043
IDA*
八数码问题直接dfs/bfs,时间复杂度很高,需要一个很好的剪枝,使用IDA*。当前状态到达目标状态最短(理想)距离h是各个数字直接到达目的地,如果h+当前步数>最深搜索的步数,那么这种情况就不去考虑。对于判断八数码是否可解,需要用到逆序数的知识((╯‵□′)╯︵┻━┻这谁会知道啊):x的移动并不影响整个数列逆序数的奇偶性,也就是说若给定初始状态逆序数的奇偶性与目标状态不同,则unsolvable。去重用到了状态压缩,因为数字数量级为10^9,使用set/map存储状态。(坑点是多组数据,但是题目没说)
代码如下:
#include<cstdio>
#include<cmath>
#include<iostream>
#include<set>
using namespace std;
const int standard=;
set<int>exist;
int a[],state[][],deep,sx,sy,step[];
char c;
int dx[]={,,-,};
int dy[]={-,,,};
char towards[]={'l','r','u','d'};
int index;
bool ok=;
int inversions(){//求逆序数
int num=;
for(int i=;i<;++i)
for(int j=i+;j<;++j)
if(a[i]!=&&a[j]!=)
if(a[j]<a[i])num++;
return num;
}
int zip(){
int s=;
for(int i=;i<;++i)
for(int j=;j<;++j)
s=s*+state[i][j];
return s;
}
int Astar(){//无视障碍物直接到达目的地所需步数
int h=;
for(int i=;i<;++i)
for(int j=;j<;++j){
int num=state[i][j];
if(num!=){
int x=(num-)/;
int y=(num-)%;
h+=abs(x-i)+abs(y-j);
}
}
return h;
}
void IDAstar(int px,int py,int nowdeep){
if(ok)return;
int h=Astar();
if(!h&&zip()==standard){
ok=;
return;
}
if(nowdeep+h>deep)return;//A*估价函数
for(int i=;i<;++i){
int x=px+dx[i];
int y=py+dy[i];
if(<=x&&x<&&<=y&&y<){
swap(state[px][py],state[x][y]);
int s=zip();
if(!exist.count(s)){
step[index++]=i;
exist.insert(s);
IDAstar(x,y,nowdeep+);
if(ok)return;
exist.erase(s);
step[--index]=;
}
swap(state[px][py],state[x][y]);
}
}
}
int main(void){
char k;
while(cin>>k){
ok=;
index=;
for(int i=;i<;++i){
if(i==)c=k;
else cin>>c;
if(''<=c&&c<='')
a[i]=c-'';
else a[i]=;
}
if(inversions()&){//若有解,逆序数的奇偶性和standard相同
cout<<"unsolvable"<<endl;
continue;
}
for(int i=;i<;++i)
for(int j=;j<;++j){
state[i][j]=a[*i+j];
if(state[i][j]==)
sx=i,sy=j;
}
int s=zip();
if(s==standard){
cout<<""<<endl;
continue;
}
for(deep=;!ok;++deep){
exist.clear();
exist.insert(s);
IDAstar(sx,sy,);
}
for(int i=;i<index;++i)
cout<<towards[step[i]];
cout<<""<<endl;
}
}
随机推荐
- BZOJ1013 [JSOI2008]球形空间产生器sphere(高斯消元)
1013: [JSOI2008]球形空间产生器sphere Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4846 Solved: 2525[Subm ...
- Transform.TransformDirection 变换方向
官方描述: JavaScript ⇒ TransformDirection(direction: Vector3): Vector3; C# ⇒ Vector3 TransformDirection( ...
- xtrabackup在线备份主库,搭建slave,使用gtid模式
mysql:5.6.29xtrabackup:2.2.10master:192.168.166.129slave:192.168.166.131mysql数据目录:/data/mysqlmysql备份 ...
- Linux下的暴力密码在线破解工具Hydra安装及其组件安装-使用
Linux下的暴力密码在线破解工具Hydra安装及其组件安装-使用 hydra可以破解: http://www.thc.org/thc-hydra,可支持AFP, Cisco AAA, Cisco a ...
- javascript实现页面右侧在线客服始终跟随鼠标滚动而上下滚动且始终位于屏幕中间
效果如图,右侧的联系一栏始终位于页面的中间位置,且随着页面的上下滚动而滚动跟随 css的话没什么好说的,看图 代码 window.onload=window.onresize=window.onscr ...
- Java 并发 中断线程
Java 并发 中断线程 @author ixenos 对Runnable.run()方法的三种处置情况 1.在Runnable.run()方法的中间中断它 2.等待该方法到达对cancel标志的测试 ...
- Time.timeScale、游戏暂停
原文链接 项目里面一直在用Time.timeScale来做游戏的 1倍 2倍整体加速,今天我仔细看了一下Time.timeScale才发现之前我理解错了一些东西. Time.timeScale可以控制 ...
- Hololens生成与安装(旁加载)应用
Hololens生成应用的几种方式: 一:HoloToolkit编辑器生成appx应用 二:Vistul Studio 2015 创建应用 旁加载概述: 你可以将应用旁加载到你的设备,而无需将它们提交 ...
- 为什么switch...case语句比if...else执行效率高
在C语言中,教科书告诉我们switch...case...语句比if...else if...else执行效率要高,但这到底是为什么呢?本文尝试从汇编的角度予以分析并揭晓其中的奥秘. 第一步,写一个d ...
- Scala Singleton对象
Scala Object: scala没有静态的修饰符,例如Java中的static.但是Scala提供了Object类型,object下的成员都是静态的,比较像Java的静态类.不同在于Scala的 ...