hdu 1043 Eight 经典八数码问题

题意描述:给出一个3×3的矩阵(包含1~8数字和一个字母x),经过一些移动格子上的数后得到连续的1~8,最后一格是x,要求最小移动步数。
算法分析:经典的八数码问题。八数码属于搜索方面的问题,经典解法有bfs、A*、IDA*等等。网上资料很多,这里简单介绍一下A*。
A*:f=g+h函数。g表示从起点到当前点的移动步数,h表示对当前点到目标点的最小移动步数的预测。除去起点和目标点,我们走在任意一点上的时候,下一步很容易想到应该选择f较小的继续。(对于h的计算我们可以用曼哈顿距离公式)
康托展开:这道题里面的作用在于实施hash函数,对于当前这一步后得到一个新的矩阵,用康托展开公式计算这个矩阵的hash值,用在宽搜时判断。

还有一点优化的地方:判断当前矩阵是否可以达到目标矩阵(矩阵里两个数实施交换后,逆序数的奇偶性和目标矩阵一致才可以有机会达到目标矩阵)

const int maxn=10;
const int M = 400000+10;struct node
{int mase[3][3];int x,y;int f,g,h;int flag;friend bool operator < (node a,node b){return a.f > b.f;}
}start,tail;
int pre[M],v[M];char str[4]={'u','d','l','r' };
int Can[10]={1,1,2,6,24,120,720,5040,40320 };
const int destination=46234;
int Cantor(node cur) ///康托展开
{int an[10],k=0;for (int i=0 ;i<3 ;i++)for (int j=0 ;j<3 ;j++)an[k++]=cur.mase[i][j];int sum=0;for (int i=0 ;i<9 ;i++){int k=0;for (int j=i+1 ;j<9 ;j++)if (an[i]>an[j]) k++;sum += k*Can[9-i-1];}return sum+1;
}int is_ok(node an) ///判断此时奇偶性
{int a[10],k=0;for (int i=0 ;i<3 ;i++)for (int j=0 ;j<3 ;j++)a[k++]=an.mase[i][j];int sum=0;for (int i=0 ;i<k ;i++) if (a[i]!=0)for (int j=0 ;j<i ;j++)if (a[j]!=0 && a[j]>a[i]) sum ++ ;if (sum&1) return 0;return 1;
}void print(node cur)
{string ans;int sum=destination;while (pre[sum] != -1){switch (v[sum]) {case 0 : ans += str[0];break;case 1 : ans += str[1];break;case 2 : ans += str[2];break;case 3 : ans += str[3];break;}sum=pre[sum];}int len=ans.size() ;for (int i=len-1 ;i>=0 ;i--) putchar(ans[i]);return ;
}pair<int,int> pii[10];
int getH(node cur)
{int r=0,c=0;for (int i=1 ;i<=9 ;i++){pii[i%9].first=r ;pii[i%9].second=c;c++;if (c==3) {r++;c=0; }}int sum=0;for (int i=0 ;i<3 ;i++){for (int j=0 ;j<3 ;j++){int u=cur.mase[i][j];sum += abs(pii[u].first-i)+abs(pii[u].second-j);}}return sum;
}int vis[M];
int an[4][2]={-1,0, 1,0, 0,-1, 0,1 };
void A_star(node cur)
{priority_queue<node> Q;cur.g=0 ;cur.h=getH(cur);cur.f=cur.g + cur.h ;cur.flag=-1;Q.push(cur);memset(vis,-1,sizeof(vis));memset(pre,-1,sizeof(pre));memset(v,-1,sizeof(v));vis[Cantor(cur) ]=1;while (!Q.empty()){cur=Q.top() ;Q.pop() ;if (Cantor(cur)==destination){
//            cout<<cur.g<<endl;
//            for (int i=0 ;i<3 ;i++)
//            {
//                for (int j=0 ;j<3 ;j++)
//                    cout<<cur.mase[i][j]<<" ";
//                cout<<endl;
//            }///输出序列print(cur);return ;}for (int i=0 ;i<4 ;i++){tail.x=cur.x+an[i][0];tail.y=cur.y+an[i][1];int x=cur.x ,y=cur.y ;for (int u=0 ;u<3 ;u++)for (int v=0 ;v<3 ;v++)tail.mase[u][v]=cur.mase[u][v];if (tail.x<0||tail.x>=3||tail.y<0||tail.y>=3) continue;swap(tail.mase[tail.x][tail.y],tail.mase[x][y]);int sum=Cantor(tail);if (vis[sum]==-1){if (is_ok(tail)==0) continue;vis[sum]=1;tail.g=cur.g+1;tail.h=getH(tail);tail.f=tail.g+tail.h;if (tail.x==x+1) tail.flag=1;else if (tail.x==x-1) tail.flag=0;else if (tail.y==y-1) tail.flag=2;else if (tail.y==y+1) tail.flag=3;pre[sum]=Cantor(cur);v[sum]=i;Q.push(tail);}}}return ;
}int main()
{char str[100];while (gets(str)){int r=0,c=0;int len=strlen(str);int ok=0;for (int i=0 ;i<len ;i++){if (str[i]>='0' && str[i]<='9'){start.mase[r][c]=str[i]-'0';c++;if (c==3) {r++;c=0; }}else if (str[i]=='x'){start.mase[r][c]=0;start.x=r ;start.y=c ;c++;if (c==3) {r++;c=0; }}}int sum=Cantor(start);if (sum==destination) {printf("\n");continue; }if (is_ok(start)==0) {printf("unsolvable\n");continue; }A_star(start);printf("\n");}return 0;
}

hdu 1043 Eight 经典八数码问题相关推荐

  1. HDU 1043 Eight(八数码)

    HDU 1043 Eight(八数码) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Oth ...

  2. HDU 1043 Eight(八数码第七境界|A*+哈希+曼哈顿距离)

    题意:八数码. 思路:将上一篇博客的估计函数h更改为求当前状态到目标状态的曼哈顿距离,因为每次都是和空格交换,所以计算的时候不计算空格的曼哈顿距离就可以满足估计函数的两条性质: 1.h(n)>h ...

  3. 1043 Eight(八数码问题 康托展开 A*算法)

    首先介绍一下A*算法: https://blog.csdn.net/qq_40061421/article/details/81915573 然后是康托展开: https://blog.csdn.ne ...

  4. hdu 1043 ,pku 1077 Eight ,八数码问题

    某位神牛曾说过,此题是涉及到人生完不完整的一道题.. Goodness大牛曾总结了 八数码的八重境界 : http://www.cnblogs.com/goodness/archive/2010/05 ...

  5. Eight HDU - 1043(八数码+搜索)

    题意: 就是还原八数码.输出操作. 题目: The 15-puzzle has been around for over 100 years; even if you don't know it by ...

  6. HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法

    先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...

  7. hdu1043 经典的八数码问题 逆向bfs打表 + 逆序数

    题意: 题意就是八数码,给了一个3 * 3 的矩阵,上面有八个数字,有一个位置是空的,每次空的位置可以和他相邻的数字换位置,给你一些起始状态 ,给了一个最终状态,让你输出怎么变换才能达到目的. 思路: ...

  8. C++解题报告:详解经典搜索难题——八数码问题( 双向BFS A* 求解)

    引言 AC这道八数码问题,你和楼教主就是兄弟了... 题目描述 在一个3*3的九宫格棋盘里,放有8个数码,数码的数字分别是1~8.棋盘中还有一个位置是空着的,用0表示.可以通过在九宫格里平移数码来改变 ...

  9. 【hdu 1043】Eight

    [题目链接]:http://acm.hdu.edu.cn/showproblem.php?pid=1043 [题意] 会给你很多组数据; 让你输出这组数据到目标状态的具体步骤; [题解] 从12345 ...

最新文章

  1. 史上自定义 JavaScript 函数Top 10
  2. 选本还是从缓存设计理念选择更好
  3. vmware虚拟机克隆后,启动网卡报错device eth0 does not seem to be present, delaying initialization...
  4. 伪静态技术(SEO) 摘自:http://bbs.admin5.com/thread-8522290-1-1.html
  5. apache solr velocity 注入远程命令执行漏洞 (cve-2019-17558)
  6. 并发编程--线程池与进程池
  7. 为什么有的S4系统看不到Adapt UI按钮
  8. 谈谈NLP下一个主战场:万亿参数的预训练模型!
  9. 指针%p输出的一些认识
  10. 魔兽美服服务器维护,美服《魔兽世界》低人口密度服务器合并计划最新动态
  11. 传输层端口号的范围是多少?被分为哪两部分_6.传输层协议
  12. java图书管理系统源代码_高校社团管理系统(ssm+mysql)
  13. poj 1159 Palindrome(dp)
  14. 可代替 ASM,使用 AnnotationProcessor 做代码插桩
  15. 在微信小程序中使用条形码生成器
  16. ABBYY FineReader 12 破解版(附注册码)
  17. linux命令 查看分辨率,Linux 下怎么用命令修改分辨率
  18. c语言程序设计医院排队功能,C语言-医院挂号排队系统.doc
  19. 手机定位--GPS定位,基站定位,辅助定位
  20. 第1040期机器学习日报(2017-07-24)

热门文章

  1. 测试 软通动力软件测试机试_软通动力软件测试面试经验
  2. node js 写按键精灵_带有按键的Node.js Raw模式
  3. 计算机科学与技术脑电波,科学“读心术”,当脑电波扫描图遇到人工智能
  4. hexo博客yilia主题_缺失模块_解决方案
  5. docker安装bind
  6. Microsoft_SQL_Server_自定义函数整理大全
  7. 打小都说我聪明,自从学了Linux,我才如梦初醒
  8. 安卓最牛教材!2021大厂Android面试经历,吐血整理
  9. 罗斯蒙特1056ph电极_Rosemount/罗斯蒙特1056-02-20-36-AN-UL 分析仪PH电极
  10. 高德地图API JS实现获取坐标和回显点标记