HDU1043、以及POJ1077上面都有这道题目,可以说是搜索里的非常经典的题目了。

poj上面的数据真的是弱,由于只有一组数据,简单bfs直接就可以过掉。

前前后后捣鼓了能有6个小时,才把这道题目在HDU上以4500ms的微弱优势通过。。。。。。。

我的思路一开始是简单的bfs,在HDU上超时。然后改用A*搜索,尝试了3种启发函数,才微弱的过掉。。。。我看别人的代码也是A*算法,而且启发函数写的跟我一样,为什么就几百ms过掉了呢。。。。还是不明白。。。。

思路:

(1)本题比较关键的一点就是判重问题,怎么样保证同一个状态只能被访问一次,涉及到状态的表示问题。

而状态其实是一个排列数,我们现在想要把一个排列数Hash到一个整数上,这就用到了康托展开的方法。(见我前一个博文)

(2)第二个比较关键的地方就是启发函数的选取

启发函数设置了两个参数:

val:当前状态到目标状态的哈密顿距离。

step: 当前已经移动的次数。

函数1:val + step :在poj上以67ms通过,在HDU上TLE

函数2:step为第一关键字,val为第二关键字 在poj上以760ms通过,在HDU当然TLE

函数3:以val为第一关键字,以step为第二关键字,在poj上以0ms通过,在HDU上以4500ms通过

这里还有一个需要注意的地方,就是无解情况的判定:

有一个定理,当两个状态的逆序数的奇偶性相同的时候,他们可以互相到达。

否则,他们无法互相到达,这个定理可以快速完成无解判定。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
class cantor{public:int fac_dp[11];int fac(int i){if(fac_dp[i]) return fac_dp[i];return fac_dp[i] = i*fac(i-1);}void init(){memset(fac_dp,0,sizeof(fac_dp));fac_dp[0] = 1;fac(10);}int encode(int num[],int n){int ans = 0;for(int i = 0;i < n;i++){int cnt = 0;for(int j = i;j < n;j++){if(num[i] > num[j])cnt++;}ans += fac_dp[n-i-1] * cnt;}return ans;}void decode(int ans[],int num,int n){int used[11];for(int i = 0;i < n;i++) used[i] = 0;for(int i = 0;i < n;i++){int cnt = num/fac_dp[n-i-1];int r = num%fac_dp[n-i-1];for(int j = 0;j < n;j++){if(!cnt && !used[j]){used[j] = 1;ans[i] = j;break;}if(!used[j]){cnt--;}}num = r;}}
};
struct node{int key;int val;int step;int loc;int x[9];friend bool operator<(node n1,node n2){if(n1.val == n2.val){return n1.step > n2.step;}return n1.val > n2.val;}node(int a,int b,int c,int loc):key(a),val(b),step(c),loc(loc){}
};
int a[11],b[11];
const int MAX = 3628800;
int pre[MAX];
int preid[MAX];
int visited[MAX];
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,-1,1};
int tarmp[9] = {8,0,1,2,3,4,5,6,7};
char dc[4] = {'d','u','l','r'};
cantor ct;
void prtpath(int end,int beg){char stk[100];int cnt = 0;while(end != beg){stk[cnt++] = dc[pre[end]]; end = preid[end];}while(cnt){putchar(stk[--cnt]);}puts("");
}
bool check(int arr[]){int sum = 0;for(int i = 0;i < 9;i++){if(arr[i] == 0) continue;for(int j = i;j < 9;j++){if(arr[j] == 0) continue;if(arr[i] > arr[j]) sum++;}}return sum%2 == 0;
}
int calc(int arr[]){int ans = 0;for(int i = 0;i < 9;i++){ans += abs(i/3 - tarmp[arr[i]]/3) + abs(i%3 - (tarmp[arr[i]]%3));}return ans;
}
int main(){ ct.init();char c;while(~scanf(" %c",&c)){memset(visited,0,sizeof(visited));memset(pre,0,sizeof(pre));if(c == 'x') a[0] = 0;else a[0] = c - '0';for(int i = 1;i < 9;i++){    scanf(" %c",&c);if(c == 'x'){a[i] = 0;}else{a[i] = c - '0';}}if(!check(a)){puts("unsolvable");continue;}for(int i = 0;i < 8;i++) b[i] = i+1;b[8] = 0;int tar = ct.encode(b,9);int code = ct.encode(a,9);preid[code] = code;priority_queue<node> Q; int lc = -1;while(a[++lc] != 0);node cur = node(code,calc(a),0,lc);for(int i = 0;i < 9;i++) cur.x[i] = a[i];Q.push(cur);visited[code] = 1;int f = 0;while(!Q.empty()){node nn = Q.top();Q.pop();int ccd = nn.key;if(ccd == tar){//找到了!  //cout<<"YES"<<endl;prtpath(tar,code);f = 1;break;}int lc = nn.loc;int x = lc / 3;int y = lc % 3;nn.step ++;for(int i = 0;i < 4;i++){int nx = dx[i] + x;int ny = dy[i] + y;if(nx >= 0 && nx < 3 && ny >= 0 && ny < 3){int nlc = nx * 3 + ny;swap(nn.x[lc],nn.x[nlc]);int ncd = ct.encode(nn.x,9);if(!visited[ncd]){pre[ncd] = i;preid[ncd] = ccd;nn.key = ncd;nn.val = calc(nn.x);nn.loc = nlc;Q.push(nn);visited[ncd] = 1;}swap(nn.x[lc],nn.x[nlc]);}}}if(!f){puts("unsolvable");}}
}

搜索训练1 [8数码问题]相关推荐

  1. 《人工智能》实验二——搜索技术(八数码问题)

    必须记住下一步还可以走哪些点--OPEN表(记录还没有扩展的点) 必须记住哪些点走过了--CLOSED表(记录已经扩展的点 广度优先搜索 在应用BFS算法进行八数码问题搜索时需要open和closed ...

  2. Spark网格搜索——训练验证集拆分

    前言 Spark内的网格搜索主要有两种评估流程,分别是 交叉验证 和 训练验证集拆分,这篇文章主要介绍训练验证集拆分的具体流程 数据集划分 训练集.验证集.测试集 训练集(train):训练模型 验证 ...

  3. 【人工智能】八数码问题:广度搜索、深度搜索

    应用广度搜索BFS和深度搜索DFS解决八数码问题,广度搜索和深度搜索都是盲目搜索,相关理论知识,算法过程:问题求解:状态空间图和盲目搜索. 参考:7种方法求解八数码问题 Python实现A*算法解决N ...

  4. 调参到头秃?你需要这份自动超参搜索技术攻略

    点击上方,选择星标或置顶,不定期资源大放送! 阅读大概需要13分钟Follow小博主,每天更新前沿干货 来源:PaperWeekly本文约4845字,建议阅读9分钟本文介绍了自动超参搜索的系统架构及技 ...

  5. 搜索和其他机器学习问题有什么不同?

    本文首发于 vivo互联网技术 微信公众号 作者:Doug Turnbull 译者:林寿怡 目录: 一.衡量搜索的好坏 二.用机器学习生成 ranking 函数 三.单文档 机器学习排序 (point ...

  6. 数据不够怎么训练深度学习模型?不妨试试迁移学习 ——重用神经网络的结构2...

    数据不够怎么训练深度学习模型?不妨试试迁移学习 本质就是这个图!pretrained model就是你截取的部分神经网络模型(迁移学习),而nanonet就是你自己加入的网络层. 随着深度学习技术在机 ...

  7. android 可以搜索到热点 连接时显示未找到热点_魔兽世界地精经典语录:时间就是金钱!8266互联网时间显示器教程...

    今天使用ESP8266(nodemcu)做一个互联网时间显示器,没错从互联网获取时间,精准高效,简单粗暴,不用对时.入门级详细教程哦!​ 按照国际惯例先展示成品: 绑两根绳,也可以称之为手表^^ 材料 ...

  8. ICCV 2019 | 厦大提出快速NAS检索方法,四小时搜索NN结构

    点击我爱计算机视觉标星,更快获取CVML新技术 机器之心专栏 作者:郑侠武 ICCV 2019 将于 10.27-11.2 在韩国首尔召开,本次会议总共接受 1077 篇,总提交 4303 篇,接收率 ...

  9. 【华为云技术分享】自动网络搜索(NAS)在语义分割上的应用(二)

    [摘要] 本文将介绍如何基于ProxylessNAS搜索semantic segmentation模型.最终搜索得到的模型结构可在CPU上达到36 fps. 随着自动网络搜索(Neural Archi ...

最新文章

  1. 尺度空间理论与图像金字塔
  2. Linux哪个和Windows很像,Linuxfx - 这套Linux操作系统看起来和Windows 10非常类似
  3. python字典作业_python第一天作业:字典
  4. java web基础1Tomcat服务器基本知识
  5. react 哲学_细聊Concent amp; Recoil , 探索react数据流的新开发模式
  6. android 控件宽度自适应_Android中让图片自适应控件的大小的方法
  7. 【Flink】SqlValidatorException: Column xxx not found in any table
  8. 【RLchina第六讲】Imitation Learning
  9. 高并发大容量 NoSQL 解决方案探索
  10. hdoj2602:Bone Collector(01背包问题-dp-模版题)
  11. 推荐一些小而美的互联网公司
  12. 软件测试类型-文档测试
  13. word2016 图片去底灰_Word 2016 可以删除图片背景
  14. editor上传视频无法播放的问题
  15. 原来使用 Pandas 绘制图表也这么惊艳!
  16. 手机+测试网络+苹果手机软件,iOS-用手机网络测试Ipv6
  17. 双向可控硅实现 插头防插拔火花
  18. 一个控制键盘远程控制多台视频会议摄像机(转自搜狐)
  19. java jtextarea 监听文本_Java Swing JTextArea文本区域的实现示例
  20. 你要的能做出炫酷图表的网站来啦

热门文章

  1. Java当中迭代器的使用(遍历容器ArrayList, HashSet,HashMap)
  2. [JavaWeb-Servlet]概述与快速入门
  3. [JavaWeb-HTML]HTML标签(大部分常用标签介绍)
  4. poj2182 Lost Cows-暴力
  5. 结构型模式——桥接模式
  6. ubtunu打开firefox_ubuntu中火狐浏览器问题(也许是)
  7. C语言用循环结构算平均值,C语言循环结构选择题().doc
  8. matlab 传感器的迟滞,MATLAB PI迟滞模型问题
  9. Ubuntu下用eclipse调试caffe code
  10. (CCPC 2020 网络选拔赛)HDU 6900 Residual Polynomial(分治 + NTT)