标签:target div 个数 problem ace mil 一定要注意了 移动 namespace
<题目链接>
题目大意:
给出一个3×3的矩阵(包含1~8数字和一个字母x),经过一些移动格子上的数后得到连续的1~8,最后一格是x,要求最小移动步数。
解题分析:
本题用BFS来寻找路径,为了降低复杂度,用BFS从最终的目标状态开始处理,将所有搜索到状态以及对应的路径打表记录,然后对于输入的矩阵,直接查表输出答案 即可,本题还有一个难点,就是如何判断记录已经搜索过的状态,如果使用map+string(矩阵看成一维)会超时,所以我们这里用康拓展开式来记录状态。
#include<cstdio> #include<iostream> #include<queue> using namespace std; typedef struct nn { char way; //记录操作 int fath; //记录父节点,用于记录路径 }node1; typedef struct nod { int aa[10]; int n; //n为9在aa中的位置 int son; //记录aa的康拓展开式 }node2; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}},fac[10]; node1 Node[370000];//节点 void set_fac()//计算0到8的阶层 { fac[0]=1; for(int i=1;i<=8;i++) fac[i]=fac[i-1]*i; } int cantor(int aa[])//康托展开,掌握康拓展开的方法 { int ans=0; for(int i=0;i<9;i++) { int k=0; for(int j=i+1;j<9;j++) if(aa[i]>aa[j]) k++; ans+=k*fac[8-i]; //i点以后比aa[i]小的数的个数*((n-i)-1)! 之和 } return ans; } void bfs(int a[]) { queue<node2>Q; node2 now,next; for(int i=0;i<9;i++) now.aa[i]=a[i]; now.n=8;now.son=0; Node[now.son].fath=0; //把最终父节点记为0,也就是本身 Q.push(now); while(!Q.empty()) { now=Q.front(); Q.pop(); for(int k=0;k<4;k++) { next=now; int tx=now.n/3+dir[k][1]; int ty=now.n%3+dir[k][0]; if(ty>=0&&tx>=0&&ty<3&&tx<3) { next.n=tx*3+ty; int tem=next.aa[next.n]; next.aa[next.n]=next.aa[now.n]; next.aa[now.n]=tem; next.son=cantor(next.aa); if(Node[next.son].fath==-1) //为-1时表示这个点没有访问过,那么放入队列 { Node[next.son].fath=now.son; //当前节点的父节点就是上一个节点 if(k==0)Node[next.son].way=‘l‘;//一定要注意了,k=0是向右走,但我们是从终止状态往回搜,所以直接记录相反的方向 if(k==1)Node[next.son].way=‘r‘; if(k==2)Node[next.son].way=‘u‘; if(k==3)Node[next.son].way=‘d‘; Q.push(next); } } } } } int main() { int i,j,s,ss[10],a[10]; for(i=0;i<9;i++)//目标状态 a[i]=i+1; //建立目标一维矩阵,把x看成9 for(i=0;i<370000;i++) Node[i].fath=-1; set_fac(); //计算阶层 bfs(a); //将从最终状态能够延伸出去的所有状态以及对应路径提前打表记录 char str[50]; while(gets(str)) { for(i=0,j=0;str[i]!=‘\0‘;i++)//把字符串变成数子 { if(str[i]==‘x‘) ss[j++]=9; //把x变为数子9 else if(str[i]>=‘0‘&&str[i]<=‘8‘) ss[j++]=str[i]-‘0‘; } s=cantor(ss); //算出初态康托值 if(Node[s].fath==-1) {printf("unsolvable\n");continue;} //不能变成目标,因为当从起点开始搜索的时候,fath表示搜索到某 //点时,上一个点的状态,所以,如果s.fath==-1时,表示这个矩阵根本就延伸不出去,不可能达到目标状态 while(s!=0) { printf("%c",Node[s].way); s=Node[s].fath; } printf("\n"); } }
2018-09-06
hdu 1043 Eight (八数码问题)【BFS】+【康拓展开】
标签:target div 个数 problem ace mil 一定要注意了 移动 namespace
原文地址:https://www.cnblogs.com/00isok/p/9595726.html