搜索训练1 [8数码问题]

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


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321734.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【招聘(北京)】.NETCORE开发工程师(微服务方向)

组织&#xff1a;华汽集团北京研发中心位置&#xff1a;北京市朝阳区焦奥中心官网&#xff1a;www.sinoauto.com邮箱&#xff1a;taoxu.weisinoauto.com 项目&#xff1a;打造面向国内汽车后市场用户的一站式云服务平台&#xff08;华汽云&#xff09;&#xff0c;形态包括B2B、…

2017西安交大ACM小学期数据结构 [分块,区间修改,单点查询]

Problem A 发布时间: 2017年6月28日 09:29 最后更新: 2017年6月28日 13:03 时间限制: 1000ms 内存限制: 32M 描述 给定一个长度为n的序列a1, a2, ..., an给出q个操作, 操作分为两种 对于形如1xyz的操作, 将下标介于[x,y]的元素加上z, 满足1≤x≤y≤n, 1≤z≤105对于形如2…

17、java中的集合(4)

之前单列集合只说过了List系列的集合&#xff0c;接下来再说一下Set集合系列&#xff0c;Set集合是无序集合&#xff08;存取顺序不一致&#xff09;&#xff0c;不允许添加相同元素&#xff0c;Set的实现依赖于Map集合&#xff0c;可以将Set集合看作Map集合键的集合&#xff0…

U92904-画地为佬【二分,结论】

正题 题目链接:https://www.luogu.org/problem/U92904?contestId23574 题目大意 用mmm根长度为1的火柴求能够圈住的最多块的地。 解题思路 显然如果刚好能够围成一个正方形那么一定是最优的&#xff0c;那么我们先将能够围成的围成一个最大的正方形&#xff0c;然后剩下的在…

确保线程安全下使用Queue的Enqueue和Dequeue

场景是这样&#xff0c;假设有一台设备会触发类型为Alarm的告警信号&#xff0c;并把信号添加到一个Queue结构中&#xff0c;每隔一段时间这个Queue会被遍历检查&#xff0c;其中的每个Alarm都会调用一个相应的处理方法。问题在于&#xff0c;检查机制是基于多线程的&#xff0…

2017西安交大ACM小学期数据结构 [分块、二维矩阵]

Problem B 发布时间: 2017年6月28日 10:06 最后更新: 2017年6月28日 16:35 时间限制: 2000ms 内存限制: 32M 描述 给定一个nm的矩形, 其中第i行第j列的值为ai,j给出q个操作, 操作有两种 对于形如1x1y1x2y2z的操作, 将(x1,y1)-(x2,y2)这段矩形区域的所有元素加上z, 满足1≤…

18、java中的泛型

之前介绍集合时&#xff0c;可以看到有List<String>这样的写法&#xff0c;那么尖括号里的内容是什么呢&#xff1f;这是泛型&#xff0c;意思就是说声明的这个List集合只能存放String类型的元素。 泛型是什么&#xff1f; ‘泛’指一般、不深入&#xff0c;在这里可以认…

编写一个Java程序,其中包含三个线程: 厨师(Chef)、服务员(Waiter)和顾客(Customer)

编写一个Java程序&#xff0c;其中包含三个线程: 厨师(Chef)、服务员(Waiter)和顾客(Customer)。他们的行动如下: 厨师准备菜肴&#xff0c;每次准备一个。服务员等待菜肴准备好&#xff0c;然后将其送到顾客那里。顾客等待服务员送来菜看后才开始吃。所有三个角色应该循环进行…

U86650-群鸡乱舞【矩阵乘法】

正题 题目链接:https://www.luogu.org/problem/U86650?contestId23574 题目大意 第一年有nnn只鸡&#xff0c;每只大于等于两岁的鸡每年可以生一只&#xff0c;在ttt岁时不会生鸡而会暴毙。 现在给出每只鸡的年龄&#xff0c;求第mmm年鸡的总数量。 解题思路 用fif_{i}fi​…

2017西安交大ACM小学期数据结构 [线段树]

Problem B 发布时间: 2017年7月1日 02:08 最后更新: 2017年7月1日 02:10 时间限制: 1000ms 内存限制: 64M 描述 给定一个长度为n的序列a1, a2, ..., an, 满足这个序列是一个1~n的排列 如果一个序列满足: 将序列排序后, 任意两个相邻的元素的差为1, 那么就称这个序列为&qu…

19、java中枚举

枚举是什么&#xff1f; 枚举就是将一个有限集合中的所有元素列举出来&#xff0c;在java中使用可以使用enum关键字来声明一个枚举类。 为什么使用枚举&#xff1f; 之前当用到一些常量时&#xff0c;便临时声明一个&#xff0c;这样使得代码看起来很乱&#xff0c;这里一个…

Hangfire使用ApplicationInsigts监控

起因我司目前使用清真的ApplicationInsights来做程序级监控。&#xff08;ApplicationInsights相关文档: https://azure.microsoft.com/zh-cn/services/application-insights/ &#xff09;其实一切都蛮好的&#xff0c;但是我们基于Hangfire的Job系统却无法被Ai所监控到&#…

nssl1446-小智的旅行【dp】

正题 题目大意 求一条最大的权值严格上升的路径。 解题思路 将边权排序&#xff0c;然后从fxf_xfx​转移到fy1f_y1fy​1即可&#xff0c;要注意的是因为严格上升&#xff0c;所以此次转移用的fff不能是相同权值转移时转移的。 codecodecode #include<cstdio> #include…

2017西安交大ACM小学期数据结构 [树状数组]

Problem C 发布时间: 2017年6月28日 11:38 最后更新: 2017年6月28日 16:38 时间限制: 1000ms 内存限制: 32M 描述 给定一个长度为n的序列a1, a2, ..., an, 其中ai∈[1,10]给出q个操作, 操作分为两种 对于形如1xy的操作, 将ax改为y, 满足1≤x≤n, 1≤y≤10对于形如2xyz的操…

NET主流ORM框架分析

接上文我们测试了各个ORM框架的性能&#xff0c;大家可以很直观的看到各个ORM框架与原生的ADO.NET在境删改查的性能差异。这里和大家分享下我对ORM框架的理解及一些使用经验。ORM框架工作原理所有的ORM框架的工作原理都离不开下面这张图&#xff0c;只是每个框架的实现程度不同…

20、java中的类加载机制

1、类加载机制是什么&#xff1f; 类加载机制指的就是jvm将类的信息动态添加到内存并使用的一种机制。 2、那么类加载的具体流程是什么呢&#xff1f; 一般说类加载只有三步&#xff1a;加载、连接和初始化&#xff0c;其中连接包括验证、准备和解析&#xff0c;用于将运行时加…

nssl1447-小智的糖果【dp】

正题 题目大意 长度为nnn的序列&#xff0c;mmm个位置要求两边都比他大&#xff0c;kkk个位置要求两边都比他小。求序列个数。 解题思路 若第xxx个位置为山峰&#xff0c;那么ax−1<ax>ax1a_{x-1}<a_x>a_{x1}ax−1​<ax​>ax1​&#xff0c;我们用upiup_iu…

21、java中的反射机制

先推荐安装一个 eclipse 的反编译插件 Enhanced Class Decompiler 是什么&#xff1f; 在说反射之前先说一下编译时类型和运行时类型&#xff0c;大家都知道List是一个接口&#xff0c;它是不可以被实例化的&#xff0c;但是可以通过多态实现&#xff1a;List list new Arra…

【北京】BXUG第12期活动基于 .NET Core构建微服务和Xamarin

分享主题&#xff1a;基于 .NET Core构建微服务实战分享分享者&#xff1a;薛锋 北京切尔思科技架构师 兼任东北大学信息安全工程师和技术主播&#xff0c;行业内专注于研究 .NET Core和Web应用&#xff0c;具有比较扎实的技术基础和数年的从业经历。在GitHub上主持数个开…

2017西安交大ACM小学期数据结构 [树状数组,极大值]

Problem D 发布时间: 2017年6月28日 10:51 最后更新: 2017年6月28日 16:38 时间限制: 1000ms 内存限制: 32M 描述 给定一个长度为n的序列a1, a2, ..., an当k满足2≤k≤n−1, ak>ak−1且ak>ak1时, 将元素k称为极大值点, 给出q个操作, 操作分为两种 对于形如1xy的操作…