HDU-3567 Eight II
2018-03-09 23:32
155 查看
八数码问题,给出初始状态和结束状态,要输出最短移动路径中字典序最小的那个,输入保证有解因为数据量比较多,不能单纯的BFS,双向BFS也不能保证字典序,这里利用了映射的思想以及打表
先以X12345678,1X2345678.....,1234567X8,12345678X为开始进行BFS,把路径分开保存好然后将起始状态映射为以上其中的一个(X的位置一样的那个),相应的把结束状态转变过去,再寻找路径回去即可
先以X12345678,1X2345678.....,1234567X8,12345678X为开始进行BFS,把路径分开保存好然后将起始状态映射为以上其中的一个(X的位置一样的那个),相应的把结束状态转变过去,再寻找路径回去即可
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<stack> using namespace std; const int N=362880+10; const int dm[]={3,-1,1,-3}; const char mop[]={'d','l','r','u'}; //这里的移动是与dm对应的 const int ten[]={1000000000,100000000,10000000,1000000,100000,10000,1000,100,10,1}; bool vis[9] ; //访问标记 int f[9] ; //保存父节点 char op[9] ; //保存移动 int move(int n,int i) //移动 { int pos=9,tmp=n; while(pos>1) { if(n%10==0) break; n/=10; pos--; } if(pos%3==1&&i==1) return -1; if(pos%3==0&&i==2) return -1; if(pos<4&&i==3) return -1; if(pos>6&&i==0) return -1; int np=pos+dm[i]; int t=tmp%ten[np-1]/ten[np]; tmp+=ten[pos]*t; tmp-=ten[np]*t; return tmp; } int fact[9]; //编码用 void init() //初始化 { fact[0]=1; for(int i=1;i<9;i++) fact[i]=fact[i-1]*i; memset(vis,false,sizeof(vis)); memset(f,-1,sizeof(f)); } int get_code(int s) //康托展开 { int code=0; int st[9]; for(int i=8;i>=0;i--,s/=10) st[i]=s%10; for(int i=0;i<9;i++) { int cnt=0; for(int j=i+1;j<9;j++) if(st[j]<st[i]) cnt++; code+=fact[8-i]*cnt; } return code; } bool insert(int code,int k) //检查是否访问过 { if(vis[k][code]) return false; return vis[k][code]=true; } void bfs(int sta0,int k) { queue<int> q; q.push(sta0); insert(get_code(sta0),k); while(!q.empty()) //BFS,打表 { int u=q.front(); q.pop(); int codu=get_code(u); for(int i=0;i<4;i++) { int v=move(u,i); if(v==-1) continue; int code=get_code(v); if(insert(code,k)) { q.push(v); f[k][code]=codu; //记录父节点 op[k][code]=mop[i]; //记录到父节点的操作 } } } } char a[10],b[10]; int m[9]; //映射用数组 int main() { init(); int sta0=12345678,sta; //全部入队 bfs(sta0,0); sta0=102345678; bfs(sta0,1); sta0=120345678; bfs(sta0,2); sta0=123045678; bfs(sta0,3); sta0=123405678; bfs(sta0,4); sta0=123450678; bfs(sta0,5); sta0=123456078; bfs(sta0,6); sta0=123456708; bfs(sta0,7); sta0=123456780; bfs(sta0,8); int T,kase=0; scanf("%d",&T); while(T--) { sta=sta0=0; int t=1,k; m[0]=0; scanf("%s",a); for(int i=0;i<9;i++) if(a[i]!='X') m[a[i]-'0']=t++; //映射 else k=i; scanf("%s",b); for(int i=0;i<9;i++) { sta*=10; if(b[i]!='X') sta+=m[b[i]-'0']; //转化后的状态 } int code=get_code(sta),cnt=0;; stack<char> s; while(f[k][code]!=-1) //寻找父节点,将移动操作入栈 { s.push(op[k][code]); code=f[k][code]; cnt++; } printf("Case %d: %d\n",++kase,cnt); //输出 while(!s.empty()) { printf("%c",s.top()); s.pop(); } printf("\n"); } return 0; }
相关文章推荐
- HDU 3567 Eight II (搜索)
- HDU 3567 Eight II 预处理+bfs+hash
- HDU - 3567 Eight II (bfs预处理 + 康托) [kuangbin带你飞]专题二
- HDU 3567 Eight II
- HDU 3567 Eight II
- HDU 3567 Eight II 八数码(2)
- hdu 3567 Eight II (bfs+康托展开+预处理)
- HDU 3567 - Eight II
- HDU 3567 Eight II 八数码(2)
- hdu 3567 Eight II 八数码 双向BFS
- HDU 3567 Eight II
- HDU-3567 Eight II
- HDU 3567 Eight II
- hdu 1430+hdu 3567(预处理)
- HDU(3567):八数码问题(升级版)——双BFS
- HDU 3567
- HDU - 3567 IDA* + 曼哈顿距离 + 康托 [kuangbin带你飞]专题二
- Eight II HDU - 3567
- [BFS + 打表] HDU 3567
- hdu 3567 康托展开 +BFS