http://poj.org/problem?id=1077

http://acm.hdu.edu.cn/showproblem.php?pid=1043

X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0!。这就是康托展开。康拓展开可以用来表示排列状态,对于本题的9个数字的所有排列只需要9位,所有状态总共362880个.对每个状态,我们都能得到一个不重复的状态编号,用这个状态编号可以查重

Astar算法,就是一个给所有状态一个评估函数,优先选取较优状态向下搜的最好优先直接搜索算法,对于本题,我们设F(n)=g(n)+h(n)为估价函数,设g(n)为到达该状态已经走过的步数,h(n)为到最终答案的曼哈顿距离

因为该拼图不能改变除了x以外的数字的逆序数奇偶性,所以若x以外的数字逆序数为奇数,则无法得到答案,直接输出

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cctype>
using namespace std;
const int base[9]={1,1,2,6,24,120,720,5040,40320};
const int dx[4]={1,-1,0,0};
const int dy[4]={0,0,1,-1};
const int maxh=362880;
const int des=0;
struct pnt{
int maz[3][3];
int h,g;
int x,y;
int hashCode;
bool operator < (pnt p)const {
return h+g!=p.h+p.g?h+g>p.h+p.g:g>p.g;
}
int gethashcode(){
int ans=0;
for(int i=0;i<9;i++){
int cnt=0;
for(int j=0;j<i;j++){
if(maz[j/3][j%3]>maz[i/3][i%3]){
cnt++;
}
}
ans+=base[i]*cnt;
}
return hashCode=ans;
}
int geth(){
int ans=0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
int t=maz[i][j]-1;
if(t<9) ans+=abs(i-t/3)+abs(j-t%3);
}
}
return ans;
}
bool judge(){
int cnt=0;
for(int i=0;i<9;i++){
for(int j=0;j<i;j++){
if(maz[i/3][i%3]<9&&maz[j/3][j%3]<9&&maz[i/3][i%3]<maz[j/3][j%3])cnt++;
}
}
return (cnt&1)==0;
}
};
bool in(int tx,int ty){
return tx>=0&&tx<3&&ty>=0&&ty<3;
} int vis[maxh+1];
int pre[maxh+1]; void astar(pnt s){
priority_queue <pnt>que;
que.push(s);
while(!que.empty()){
pnt f=que.top();que.pop();
for(int i=0;i<4;i++){
pnt t=f;
t.x+=dx[i];
t.y+=dy[i];
if(in(t.x,t.y)){
swap(t.maz[t.x][t.y],t.maz[f.x][f.y]);
t.hashCode=t.gethashcode();
if(vis[t.hashCode]==-1){
vis[t.hashCode]=i;
t.g++;
pre[t.hashCode]=f.hashCode;
t.h=t.geth();
que.push(t);
}
if(t.hashCode==des)return ;
}
}
}
}
char ans[maxh+1];
void print(){
int nxt=des;
int len=0;
while(pre[nxt]!=-1){
switch(vis[nxt]){
case 0:
ans[len++]='d';
break;
case 1:
ans[len++]='u';
break;
case 2:
ans[len++]='r';
break;
case 3:
ans[len++]='l';
break;
}
nxt=pre[nxt];
}
for(int i=len-1;i>=0;i--){
putchar(ans[i]);
}
puts("");
}
char buff[300];
pnt s;
bool input(){
if(gets(buff)==NULL)return false;
int j=0;
for(int i=0;i<9;i++){
while(!isalnum(buff[j])){j++;}
if(buff[j]>='0'&&buff[j]<='9'){
s.maz[i/3][i%3]=buff[j]-'0';
}
else{
s.maz[i/3][i%3]=9;
s.x=i/3;
s.y=i%3;
}
j++;
}
return true;
}
int main(){
while(input()){
memset(vis,-1,sizeof(vis));
memset(pre,-1,sizeof(pre));
if(!s.judge()){
puts("unsolvable");
continue;
}
s.hashCode=s.gethashcode();
if(s.hashCode==des){
puts("");
continue;
}
vis[s.hashCode]=-2;
s.g=0;s.h=s.geth();
astar(s);
print();
}
return 0;
}

  

POJ 1077 && HDU 1043 Eight A*算法,bfs,康托展开,hash 难度:3的更多相关文章

  1. HDU 1043 Eight(双向BFS+康托展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...

  2. Eight POJ - 1077 HDU - 1043 八数码

    Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...

  3. HDU - 1430 魔板 【BFS + 康托展开 + 哈希】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1430 思路 我刚开始 想到的 就是 康托展开 但是这个题目是 多组输入 即使用 康托展开 也是会T的 ...

  4. POJ 1077 HDU 1043 Eight (IDA*)

    题意就不用再说明了吧......如此经典 之前想用双向广搜.a*来写,但总觉得无力,现在用IDA*感觉其他的解法都弱爆了..............想法活跃,时间,空间消耗很小,给它跪了 启发式搜索关 ...

  5. HDU_1043 Eight 【逆向BFS + 康托展开 】【A* + 康托展开 】

    一.题目 http://acm.hdu.edu.cn/showproblem.php?pid=1043 二.两种方法 该题很明显,是一个八数码的问题,就是9宫格,里面有一个空格,外加1~8的数字,任意 ...

  6. 洛谷 P2578 [ZJOI2005]九数码游戏【bfs+康托展开】

    只有9!=362880个状态,用康托展开hash一下直接bfs即可 #include<iostream> #include<cstdio> #include<cstrin ...

  7. [算法总结]康托展开Cantor Expansion

    目录 一.关于康托展开 1.什么是康托展开 2.康托展开实现原理 二.具体实施 1.模板 一.关于康托展开 1.什么是康托展开 求出给定一个由1n个整数组成的任意排列在1n的全排列中的位置. 解决这样 ...

  8. BFS(八数码) POJ 1077 || HDOJ 1043 Eight

    题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...

  9. HDU 1043 Eight (A*算法)

    题目大意:裸的八数码问题,让你输出空格的一条合法移动路径 首先利用康托展开对排列编号,可以预处理出排列,就不必逆展开了 然后利用A*算法求解 A*算法是一种启发式搜索,具体实现要用到优先队列/堆,不同 ...

随机推荐

  1. Promise A 规范的一个简单的浏览器端实现

    简单的实现了一个promise 的规范,留着接下来模块使用.感觉还有很多能优化的地方,有时间看看源码,或者其他大神的代码 主要是Then 函数.回调有点绕人. !(function(win) { fu ...

  2. hdu 1242 Rescue

    题目链接:hdu 1242 这题也是迷宫类搜索,题意说的是 'a' 表示被拯救的人,'r' 表示搜救者(注意可能有多个),'.' 表示道路(耗费一单位时间通过),'#' 表示墙壁,'x' 代表警卫(耗 ...

  3. bignum 大数模板

    今天无意间看到一个很好的大数模板,能算加.减.乘.除等基本运算,但操作减法的时候只能大数减小数,也不支持负数,如果是两个负数的话去掉符号相加之后再取反就可以了,一正一负比较绝对值大小,然后相减.我借用 ...

  4. HTML5游戏实战(4): 20行代码实现FlappyBird

    这个系列很久没有更新了.几个月前有位读者调侃说,能不能一行代码做一个游戏呢.呵呵,接下来一段时间,我天天都在想这个问题,怎么能让GameBuilder+CanTK进一步简化游戏的开发呢.经过几个月的努 ...

  5. 关于as中的事件与回调函数

    对于Observer模式, 在as中object(被观察者)既可以用事件(event),也可以用回调函数(caller)来通知观察者(observer).那在实际的开发中到底应该选择用event还是用 ...

  6. 三张图彻底了解Java中字符串的不变性

    转载: 三张图彻底了解Java中字符串的不变性 定义一个字符串 String s = "abcd"; s中保存了string对象的引用.下面的箭头可以理解为"存储他的引用 ...

  7. call的其他应用

    看一些源码的时候常常发现例如这些的代码 Array.prototype.slice.call(arg) Object.prototype.toString.call(str) 等等 ,着一些系列的句子 ...

  8. python 练习 15

    #!/usr/bin/python # -*- coding: UTF-8 -*- for i in range(1,10): for j in range(1,10): result = i * j ...

  9. Win7下Maven的安装与配置

    简介  官网:https://maven.apache.org/ Apache Maven,是一个(特别是Java软件)项目管理及自动构建工具,由Apache软件基金会所提供.基于项目对象模型(Pro ...

  10. alert与console.log

    1.alert在页面中弹出 console.log是在控制台显示 例子 var aa="Silence"; alert(typeof(aa)); console.log(typeo ...