SOJ 1151. 魔板

来源:互联网 发布:无需网络的收音机 编辑:程序博客网 时间:2024/06/05 02:41

这题跟1150比,就是要多掌握一个康托展开,必须要排除一些已经访问过的情况而不是简单地添加,比如AA,BBBB,CCCC这些操作过后并没有改变原来的顺序,不排除的话,步数太多时,内存不够用。

康托展开就是一个全排列n!的数列与0~n!-1的一个双射,对于魔板中的任意一种状态都可以映射为一个自然数,并且是一一对应的。用于记录该状态是否被访问过。

#include<iostream>#include<string.h>#include<queue>using namespace std;int fact[8] = {0,1,2,6,24,120,720,5040};bool isVisited[40320];struct mb{int num;string op;mb(){num = 0;}bool operator==(mb &b){return num == b.num;}}; int code(mb ori){int tmp[8];int code = 0;for(int i = 7; i >= 0; i--){tmp[i] = ori.num%10;ori.num/=10;}for(int i = 0; i < 8; i++){int count = 0;for(int j = i + 1; j < 8; j++){if(tmp[i]>tmp[j]){count++;}}code += count * fact[8 - i - 1];}return code;}mb A(mb ori){mb tmp;tmp.num = ori.num%10000*10000+ori.num/10000;tmp.op = ori.op + "A";return tmp;}mb B(mb ori){mb tmp;tmp.num += ori.num%1000/10;tmp.num += ori.num%10000/1000*100;  tmp.num += ori.num%10*1000;  tmp.num += ori.num%1000000/100000*10000;  tmp.num += ori.num/1000000*100000;  tmp.num += ori.num%100000/10000*10000000;tmp.op = ori.op + "B";  return tmp;}mb C(mb ori){mb tmp;tmp.num += ori.num%10;  tmp.num += ori.num%1000000/100000*10;  tmp.num += ori.num%100/10*100;  tmp.num += ori.num%100000/1000*1000;  tmp.num += ori.num%10000000/1000000*100000;  tmp.num += ori.num%1000/100*1000000;  tmp.num += ori.num/10000000*10000000;tmp.op = ori.op + "C";return tmp;}void find(queue<mb> q,int n,mb aim){while(!q.empty()){mb tmp = q.front();q.pop();if(tmp == aim && tmp.op.size() <= n){cout << tmp.op.size() << " ";cout << tmp.op;cout << endl;return;}else{mb Amb = A(tmp);mb Bmb = B(tmp);mb Cmb = C(tmp);int ca = code(Amb);int cb = code(Bmb);int cc = code(Cmb);if(!isVisited[code(Amb)]){q.push(Amb);isVisited[ca] = true;}if(!isVisited[code(Bmb)]){q.push(Bmb);isVisited[cb] = true;}if(!isVisited[code(Cmb)]){q.push(Cmb);isVisited[cc] = true;}}if(tmp.op.size() > n){cout << -1 << endl;return;}}}int main(){int n;while(cin >> n && n != -1){int tmp;mb aim,one;queue<mb> q;memset(isVisited,false,40320); //要改输入 for(int i = 0; i < 8; i++){int tmp;cin >> tmp;aim.num = aim.num*10+tmp;}one.num = 12348765;q.push(one);find(q,n,aim);}}


0 0
原创粉丝点击