codevs1225八数码难题
Posted 那一抹落日的橙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs1225八数码难题相关的知识,希望对你有一定的参考价值。
为了做这个题,我足足花了一个晚自习,才处理好所有的细节问题,太琐碎了
现在复习知识的同时,也会穿插上一些曾经学过但是了解不深的问题,比如a*
a*最重要的就是通过估价函数来大大优化搜索,估价函数是整个a*的灵魂,通过估价函数,可以省去大量的不必要的状态,是一个非常高效的算法。
其他话都写在代码里了,考初赛考的都快虚脱了╮(╯▽╰)╭辣鸡ccf,居然连页脚下方的几几年初赛都写错了,出的题目简直爆炸,今年复赛怕不是药丸
#include<iostream> #include<cstdio> #include<vector> #include<queue> #include<cmath> #define ri register int const int mod=100003; using namespace std; bool flag[100010]; int ans,e[10][2],fx[4]={-1,0,1,0},fy[4]={0,1,0,-1}; struct in { int mmp[4][4];//地图 int ha,rx,ry,as,mn,ca;//hash值,0的坐标,当前状态步数,以及状态被压成串 bool operator <(const in &a)const { return mn+as>a.mn+a.as;//估价函数g(i)是所有点与答案当中该点所在位置的曼哈顿距离之和 } }st,ed; priority_queue<in>qwq; inline void hash(in &x)//求hash值,用于去重 { int re=1; for(ri i=1;i<=3;i++) for(ri j=1;j<=3;j++) re=(re*26+x.mmp[i][j])%mod; x.ha=re%mod; return; } inline void chu(in &a,int x)//提前预处理好状态的估价函数,0所在的位置和hash值 { a.ca=x,a.mn=0; int mo=100000000,shu=0; for(ri i=1;i<=9;i++) { shu=x/mo,a.mmp[(i-1)/3+1][i-(i-1)/3*3]=shu,x=x-x/mo*mo; a.mn+=abs((i-1)/3+1-e[shu][0])+abs(i-(i-1)/3*3-e[shu][1]); if(shu==0) a.rx=(i-1)/3+1,a.ry=i-(i-1)/3*3; mo/=10; } hash(a); } inline void ya(in &a)//将状态压缩成串 { a.ca=0; for(ri i=1;i<=3;i++) for(ri j=1;j<=3;j++) a.ca=a.ca*10+a.mmp[i][j]; } int n; inline void bfs()//a* { while(!qwq.empty()) { in qaq=qwq.top(),to; qwq.pop(); if(qaq.ha==ed.ha) { ans=qaq.as;return; } to.as=qaq.as+1; for(ri i=0;i<4;i++) { to.rx=qaq.rx+fx[i],to.ry=qaq.ry+fy[i]; if(to.rx<1||to.rx>3||to.ry<1||to.ry>3) continue; for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) to.mmp[i][j]=qaq.mmp[i][j]; swap(to.mmp[to.rx][to.ry],to.mmp[qaq.rx][qaq.ry]); ya(to); chu(to,to.ca); if(!flag[to.ha]) flag[to.ha]=1,qwq.push(to); swap(to.mmp[to.rx][to.ry],to.mmp[qaq.rx][qaq.ry]); } } } int main() { scanf("%d",&n); int m=100000000,shu=0,n1=123804765; for(int i=1;i<=9;i++) { shu=n1/m; e[shu][0]=(i-1)/3+1,e[shu][1]=i-(i-1)/3*3;//预处理好答案中的每种数字所在位置,便于一会求估价函数 n1=n1-n1/m*m,m/=10; } chu(st,n),chu(ed,123804765);//对这两个状态进行预处理,做好加入队列的准备 ya(st),ya(ed);//把状态压成个串,便于下面处理 qwq.push(st); bfs(); printf("%d",ans); }
以上是关于codevs1225八数码难题的主要内容,如果未能解决你的问题,请参考以下文章