标签:
题意:就是八数码问题,给你开始的串和结束的串,问你从开始到结束的最短且最小的变换序列是什么
分析:我们可以预处理打表,这里的这个题可以和HDU1430魔板那个题采取一样的做法
预处理打表,因为八数码问题实际上是每个小块位置的变化,上面的数字只是用来标记位置的,
所以通过映射将初末序列进行置换就好了,然后因为每次的x字符的置换位置不一样
所以需要以123456789这个初始串打9遍表就好了733ms
#include <iostream> #include <cstdio> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <cmath> #include <queue> using namespace std; const int N=5005; int fac[]= {1,1,2,6,24,120,720,5040,40320,362880}; int aim; int cantor(char s[]) { int ans=0; for(int i=1,j=8; i<=9; ++i,--j) { int tmp=0; for(int k=i+1; k<=9; ++k) if(s[i]>s[k])++tmp; ans+=(tmp*fac[j]); } return ans; } struct Node { char s[10]; int hs; }; struct asd { bool vis; char c; int pre; }o[10][362880]; queue<Node>q; void bfs(int pos) { Node a; for(int i=1; i<=9; ++i) a.s[i]=‘0‘+i; aim=a.hs=cantor(a.s); o[pos][a.hs].vis=1; q.push(a); while(!q.empty()) { a=q.front(); q.pop(); int now=a.hs; int x; for(int i=1; i<=9; ++i) if(a.s[i]==‘0‘+pos)x=i; if(x+3<10) { bool flag=0; swap(a.s[x],a.s[x+3]); a.hs=cantor(a.s); if(o[pos][a.hs].vis) flag=1; if(!flag) { o[pos][a.hs].vis=1; o[pos][a.hs].c=‘d‘; o[pos][a.hs].pre=now; q.push(a); } swap(a.s[x],a.s[x+3]); } if(x%3!=1) { bool flag=0; swap(a.s[x],a.s[x-1]); a.hs=cantor(a.s); if(o[pos][a.hs].vis) flag=1; if(!flag) { o[pos][a.hs].vis=1; o[pos][a.hs].c=‘l‘; o[pos][a.hs].pre=now; q.push(a); } swap(a.s[x],a.s[x-1]); } if(x%3) { bool flag=0; swap(a.s[x],a.s[x+1]); a.hs=cantor(a.s); if(o[pos][a.hs].vis) flag=1; if(!flag) { o[pos][a.hs].vis=1; o[pos][a.hs].c=‘r‘; o[pos][a.hs].pre=now; q.push(a); } swap(a.s[x],a.s[x+1]); } if(x-3>0) { bool flag=0; swap(a.s[x],a.s[x-3]); a.hs=cantor(a.s); if(o[pos][a.hs].vis) flag=1; if(!flag) { o[pos][a.hs].vis=1; o[pos][a.hs].c=‘u‘; o[pos][a.hs].pre=now; q.push(a); } swap(a.s[x],a.s[x-3]); } } } char s[15],t[15]; string res; void getres(int u,int pos) { while(u!=aim) { res=res+o[pos][u].c; u=o[pos][u].pre; } } char mat[13]; int main() { for(int i=0;i<326880;++i) for(int j=1;j<=9;++j) o[j][i].vis=0; for(int i=1;i<=9;++i) bfs(i); int T,cas=0; scanf("%d",&T); while(T--) { scanf("%s%s",s+1,t+1); int flag; for(int i=1;i<=9;++i) { if(s[i]==‘X‘)s[i]=‘9‘,flag=i; if(t[i]==‘X‘)t[i]=‘9‘; mat[s[i]-‘0‘]=i+‘0‘; } for(int i=1;i<=9;++i) t[i]=mat[t[i]-‘0‘]; int ans=cantor(t); res.clear(); getres(ans,flag); printf("Case %d: %d\n",++cas,res.size()); reverse(res.begin(),res.end()); cout<<res<<endl; } return 0; }
标签:
原文地址:http://www.cnblogs.com/shuguangzw/p/5252053.html