12345678 17245368 12345678 82754631
C AC
for( i=0;i<8;i++)pos[s1[i]-‘0‘]=i+1+‘0‘;for( i=0;i<8;i++)s2[i]=pos[s2[i]-‘0‘];k=kangtuo(s2);
上面一段代码的意思是:把起始目标看成了1,2,3,4,5,6,7,8 ;
列如:位置:12345678 12345678
起初: 63728145 变 12345678
终点: 86372541 成 51234876
解释一下:初:6在第1个位,那么在终点中找6用1代替,3在第2个位,在终点中找3用2代替,依次类推。
一开始我们就先按 12345678 这样的顺序建立了一棵像树一样的,如果直接从初态不进行转变的话,那么我们的结果可能有很多的走法,有可能是先走A或B都可以到目标,有多条路时,但是先走了B的路径,必须要输出小的也就是从A开始的那条路,那怎么办呢,就可以用转化的思想了,把初始状态变成12345678,这样的话,我们一开始就是从这样的顺序算出来的!!所以必须先进行转换,在从目标往上找并记下路径,一直找到最终父节点:12345678.
/************************************** *************************************** * Author:Tree * *From :http://blog.csdn.net/lttree * * Title : 魔板 * *Source: hdu 1430 * * Hint : 康托展开 BFS * *************************************** **************************************/ #include <iostream> #include <string.h> #include <string> #include <queue> using namespace std; struct Node { string str,step; }; bool vis[40320+1]; int pos[10],fac[] = {1,1,2,6,24,120,720,5040,40320}; // ans存从起点到达该点的答案 string ans[50000]; // 康托展开 int kangtuo(string a) { int i,j,t,sum; sum=0; for( i=0; i<8 ;++i) { t=0; for(j=i+1;j<8;++j) if( a[i]>a[j] ) ++t; sum+=t*fac[8-i-1]; } return sum+1; } // 按A进行变换 void move_A(string &s) { for(int i=0;i<4;++i) swap(s[i],s[i+4]); } // 按B进行变换 string move_B(string s) { string temp=s; int i; for(i=0;i<8;++i) { if( i==0 || i==4 ) temp[i]=s[i+3]; else temp[i]=s[i-1]; } return temp; } // 按C进行变换 void move_C(string &s) { swap(s[1],s[2]); swap(s[5],s[6]); swap(s[1],s[6]); } void bfs( string s ) { memset(vis,0,sizeof(vis)); queue <Node> q; Node pre,lst; pre.str=s; pre.step=""; vis[kangtuo(s)]=1; ans[kangtuo(s)]=pre.step; q.push( pre ); while( !q.empty() ) { pre=q.front(); q.pop(); lst=pre; move_A(lst.str); if( !vis[kangtuo(lst.str)] ) { lst.step+="A"; vis[kangtuo(lst.str)]=1; ans[kangtuo(lst.str)]=lst.step; q.push(lst); } lst.str=move_B(pre.str); if( !vis[kangtuo(lst.str)] ) { lst.step=pre.step+"B"; vis[kangtuo(lst.str)]=1; ans[kangtuo(lst.str)]=lst.step; q.push(lst); } lst=pre; move_C(lst.str); if( !vis[kangtuo(lst.str)] ) { lst.step+="C"; vis[kangtuo(lst.str)]=1; ans[kangtuo(lst.str)]=lst.step; q.push(lst); } } } int main() { int i,k; string s1,s2; // 预处理,从起点到各点。 bfs("12345678"); while( cin>>s1>>s2 ) { // 将顺序改过来 // 题目中 12345678 // 其实是 1234 // 8765 // 我们就按照 12348765来存储 swap(s1[4],s1[7]); swap(s1[5],s1[6]); swap(s2[4],s2[7]); swap(s2[5],s2[6]); for(i=0;i<8;i++) pos[s1[i]-‘0‘]=i+1; for(i=0;i<8;i++) s2[i]=pos[s2[i]-‘0‘];/*置换*/ k=kangtuo(s2); cout<<ans[k]<<endl; } return 0; }
ACM-康托展开+预处理BFS之魔板——hdu1430,布布扣,bubuko.com
原文地址:http://blog.csdn.net/lttree/article/details/24909959