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;
}
}

随机推荐

  1. Python小问题汇总

    现在的时间适合写点最近的小总结,这中间涉及到python/git等问题,我就从python先说起吧. 一.Python 1. Python的异常处理 因为想到自己不断尝试写小程序的话会用到抛出异常信息 ...

  2. 实体类转Json的2种方法

    首先申明所需jar包: ezmorph-1.0.6.jar jackson-all-1.7.6.jar jsoup-1.5.2.jar 一.创建一个实体类Emp. package com.hyx.en ...

  3. MongoDB应用案例:使用 MongoDB 存储日志数据

    线上运行的服务会产生大量的运行及访问日志,日志里会包含一些错误.警告.及用户行为等信息,通常服务会以文本的形式记录日志信息,这样可读性强,方便于日常定位问题,但当产生大量的日志之后,要想从大量日志里挖 ...

  4. springboot学习笔记-1 第一个springboot示例

    springboot是一个微框架,其设计的目的是为了简化spring框架的搭建和配置过程.从而使开发人员不再需要定义样板化的配置.下面是springboot的入门案例:它演示了利用springboot ...

  5. 国内的阿里云MAVEN仓库,速度很快

    配置很简单,修改conf文件夹下的settings.xml文件,添加如下镜像配置: <mirrors> <mirror> <id>alimaven</id&g ...

  6. codevs1069关押罪犯(并查集)

    题目描述 Description S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极 不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨 ...

  7. qdoc 写法

    Qdoc 注释 Qdoc注释有一些命令, 能够对文档进行组织. QDoc能识别以下3种类型的命令 主题(topic command) 主题命令确定了文档的元素,例如C++类(class),函数(fun ...

  8. 第13章 MySQL高级编程

    1.事务:一个或一系列的查询: 2.使用事务安全的表格类型(通过InnoDB): ①关闭自动提交: set autocommit=0; //若自动提交被打开,须使用如下语句开始一个事务: //  st ...

  9. C#笔记(二)变量之预定义的引用类型

    1.object类型 在C#中, object类型就是最终的父类型,所有内置类型和用户定义的类型都从它派生而 来. 这样, object类型就可以用于两个目的了: 可以使用object引用绑定任何子类 ...

  10. [ An Ac a Day ^_^ ] [kuangbin带你飞]专题八 生成树 UVA 10600 ACM Contest and Blackout 最小生成树+次小生成树

    题意就是求最小生成树和次小生成树 #include<cstdio> #include<iostream> #include<algorithm> #include& ...