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;
}
}
随机推荐
- android浏览器 源码共享
浏览器源码共享 [天天浏览器]拥有极为精简的内核,手机App大小在2MB以内,是市场上极省用户手机内存,极少占用手机资源,速度极快的浏览器,本身功能完整强大,是极速上网必备的利器. 源代码下载地址:h ...
- For循环输出一个表格
<!-- 作者:郑伟钊 时间:2017-01-16 描述:通过一个循环的嵌套输出一个表格 --> <?php header("Content-type:text/html; ...
- CodeForces 631D Messenger
$KMP$. $n=1$和$n=2$的时候可以单独计算.$n>2$时,可以拿字符和数字分别做一次匹配,然后扫描一遍判断一下就可以计算出答案了. #pragma comment(linker, & ...
- hdu1043
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#inclu ...
- 第一百二十九节,JavaScript,理解JavaScript库
JavaScript,理解JavaScript库 学习要点: 1.项目介绍 2.理解JavaScript库 3.创建基础库 从本章,我们来用之前的基础知识来写一个项目,用以巩固之前所学.那么,每个项目 ...
- 使用node.js编写脚本将JSON数据转换为SQL语句
安装依赖模块 当node.js脚本在运行的时候,需要很多支持模块,这些模块存储在node_modules文件夹中.该脚本在执行过程中需要使用到fs.string-format两个支持模块,作用分别是: ...
- 【LeetCode】30. Substring with Concatenation of All Words
You are given a string, s, and a list of words, words, that are all of the same length. Find all sta ...
- MFC中CListCtrl说明
转载:http://blog.csdn.NET/lhy2199/article/details/5177032 listctrl默认view 风格为report CListCtrl类封装"列 ...
- Chapter 2 Open Book——35
Mr. Banner called the class to order then, and I turned with relief to listen. Banner先生让大家安静听他说,然后我静 ...
- CC版本添加 LUCI
BB版本的时候,在 feeds/luci/contrib/package/luci下的Makefile文件添加上需要编译的 luci-application即可. 在CC版里改为:Feeds/luci ...