魔板
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1675 Accepted Submission(s): 353
Problem Description
在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板。魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示。任一时刻魔板的状态可用方块的颜色序列表示:从魔板的左上角开始,按顺时针方向依次写下各方块的颜色代号,所得到的数字序列即可表示此时魔板的状态。例如,序列(1,2,3,4,5,6,7,8)表示魔板状态为:
1 2 3 4
8 7 6 5
对于魔板,可施加三种不同的操作,具体操作方法如下:
A: 上下两行互换,如上图可变换为状态87654321
B: 每行同时循环右移一格,如上图可变换为41236785
C: 中间4个方块顺时针旋转一格,如上图可变换为17245368
给你魔板的初始状态与目标状态,请给出由初态到目态变换数最少的变换步骤,若有多种变换方案则取字典序最小的那种。
Input
每组测试数据包括两行,分别代表魔板的初态与目态。
Output
对每组测试数据输出满足题意的变换步骤。
Sample Input
12345678 17245368 12345678 82754631
Sample Output
C AC
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1430
这道题,BFS会超时,于是我用的双向BFS。。。
这题目中的VIS要用到 康托展开(详情可戳 http://blog.csdn.net/lttree/article/details/24798653 )
我的思路:
因为字典序,所以按照A->B->C搜索。
q队列存正向搜索的,搜索过的置1,p队列存反向搜索的,搜索过的置2。(初始化为0)
每次都扩展一层结点。
输出的时候先输出 正向的答案 再反向 输出反向的答案。
VIS数组内存到达该点时的节点和标记(1或者2)
网上说用预处理来做,
但是我试了试发现双广不会超时,就是WA。。。快被虐呆了~~o(>_<)o ~~
求大神大牛们帮忙看一下。。。
#include <iostream> #include <string.h> #include <queue> using namespace std; struct Node { char board[8],key[101]; int step; bool operator <( const Node n )const { return step<n.step; } }; struct VIS { int flag; Node k; }vis[40320+1]; int fac[] = {1,1,2,6,24,120,720,5040,40320}; char ini[8],ans[8]; // 康托展开 int kangtuo(char 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; } // 输出函数 void print( Node n,Node m ) { int i; for(i=0;i<n.step;++i) cout<<n.key[i]; for(i=m.step-1;i>=0;--i) cout<<m.key[i]; cout<<endl; } void bfs( void ) { memset(vis,0,sizeof(vis)); priority_queue <Node> q; priority_queue <Node> p; Node pre,lst; int i,sp=0; // 初始化 for(i=0;i<8;++i) pre.board[i]=ini[i]; pre.step=0; vis[kangtuo(pre.board)].flag=1; vis[kangtuo(pre.board)].k=pre; q.push(pre); for(i=0;i<8;++i) pre.board[i]=ans[i]; pre.step=0; vis[kangtuo(pre.board)].flag=2; vis[kangtuo(pre.board)].k=pre; p.push(pre); // 双向BFS while( !q.empty() && !p.empty() ) { // 将每一层都扩展 while( q.top().step==sp ) { pre=q.top(); q.pop(); // 按A方案变化 lst=pre; for(i=0; i<8; ++i) lst.board[i]=pre.board[7-i]; lst.key[lst.step++]=‘A‘; if( vis[kangtuo(lst.board)].flag==2 ) { print(lst,vis[kangtuo(lst.board)].k); return; } if( !vis[kangtuo(lst.board)].flag ) { vis[kangtuo(lst.board)].flag=1; vis[kangtuo(lst.board)].k=lst; q.push(lst); } // 按B方案变化 lst=pre; for(i=0; i<8; ++i) { if(i==0) lst.board[i]=pre.board[3]; else if(i==7) lst.board[i]=pre.board[4]; else lst.board[i]=pre.board[i-1]; } lst.key[lst.step++]=‘B‘; if( vis[kangtuo(lst.board)].flag==2 ) { print(lst,vis[kangtuo(lst.board)].k); return; } if( !vis[kangtuo(lst.board)].flag ) { vis[kangtuo(lst.board)].flag=1; vis[kangtuo(lst.board)].k=lst; q.push(lst); } // 按C方案变化 lst=pre; lst.board[1]=pre.board[6]; lst.board[2]=pre.board[1]; lst.board[5]=pre.board[2]; lst.board[6]=pre.board[5]; lst.key[lst.step++]=‘C‘; if( vis[kangtuo(lst.board)].flag==2 ) { print(lst,vis[kangtuo(lst.board)].k); return; } if( !vis[kangtuo(lst.board)].flag ) { vis[kangtuo(lst.board)].flag=1; vis[kangtuo(lst.board)].k=lst; q.push(lst); } } while( p.top().step==sp ) { pre=p.top(); p.pop(); //A lst=pre; for(i=0; i<8; ++i) lst.board[i]=pre.board[7-i]; if( vis[kangtuo(lst.board)].flag==1 ) { print(vis[kangtuo(lst.board)].k,lst); return; } if( !vis[kangtuo(lst.board)].flag ) { lst.key[lst.step++]=‘A‘; vis[kangtuo(lst.board)].flag=2; vis[kangtuo(lst.board)].k=lst; p.push(lst); } //B lst=pre; for(i=0; i<8; ++i) { if(i==0) lst.board[i]=pre.board[3]; else if(i==7) lst.board[i]=pre.board[4]; else lst.board[i]=pre.board[i-1]; } if( vis[kangtuo(lst.board)].flag==1 ) { print(vis[kangtuo(lst.board)].k,lst); return; } if( !vis[kangtuo(lst.board)].flag ) { lst.key[lst.step++]=‘B‘; vis[kangtuo(lst.board)].flag=2; vis[kangtuo(lst.board)].k=lst; p.push(lst); } //C lst=pre; lst.board[1]=pre.board[6]; lst.board[2]=pre.board[1]; lst.board[5]=pre.board[2]; lst.board[6]=pre.board[5]; if( vis[kangtuo(lst.board)].flag==1 ) { print(vis[kangtuo(lst.board)].k,lst); return; } if( !vis[kangtuo(lst.board)].flag ) { lst.key[lst.step++]=‘C‘; vis[kangtuo(lst.board)].flag=2; vis[kangtuo(lst.board)].k=lst; p.push(lst); } } ++sp; } } int main() { while( cin.getline(ini,10,‘\n‘) ) { cin.getline(ans,10,‘\n‘); bfs(); } return 0; }
ACM-双向BFS之魔板——求助ING!