在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板。这是一张有8个大小相同的格子的魔板:
1 2 3 4
8 7 6 5
我们知道魔板的每一个方格都有一种颜色。这8种颜色用前8个正整数来表示。可以用颜色的序列来表示一种魔板状态,规定从魔板的左上角开始,沿顺时针方向依次取出整数,构成一个颜色序列。对于上图的魔板状态,我们用序列(1,2,3,4,5,6,7,8)来表示。这是基本状态。
这里提供三种基本操作,分别用大写字母“A”,“B”,“C”来表示(可以通过这些操作改变魔板的状态):
“A”:交换上下两行;
“B”:将最右边的一列插入最左边;
“C”:魔板中央四格作顺时针旋转。
下面是对基本状态进行操作的示范:
A:
8 7 6 5
1 2 3 4
B:
4 1 2 3
5 8 7 6
C:
1 7 2 4
8 6 3 5
对于每种可能的状态,这三种基本操作都可以使用。
你要编程计算用最少的基本操作完成基本状态到目标状态的转换,输出基本操作序列。
【输入格式】
输入有多组测试数据
只有一行,包括8个整数,用空格分开(这些整数在范围 1——8 之间),表示目标状态。
【输出格式】
Line 1: 包括一个整数,表示最短操作序列的长度。
Line 2: 在字典序中最早出现的操作序列,用字符串表示,除最后一行外,每行输出60个字符。
Sample Input
2 6 8 4 5 7 3 1
Sample Output
7
BCABCCB
最终AC代码:
#include <bits/stdc++.h> using namespace std; //本题的难点在于 需要记录之前出现的状态 本题采用string来表示 //题干没有说明未找到的情况,还有输入的序列就是初始序列的情况(经测试,都是BFS()都是返回"" //题干虽然说每行只输出60个字符,然而没有情况超过60个字符的。。。 struct Node{ int M[2][4]; //M保存状态 string s; //累计操作 }now, nex; int des[2][4]; char op[3] = {‘A‘, ‘B‘, ‘C‘}; map<string, bool> mp; void getMatrix(char c){ int i; if(c == ‘A‘){ for(i=0; i<4; i++) nex.M[0][i] = now.M[1][i]; for(i=0; i<4; i++) nex.M[1][i] = now.M[0][i]; }else if(c == ‘B‘){ for(i=0; i<2; i++) nex.M[i][0] = now.M[i][3]; for(i=1; i<4; i++) nex.M[0][i] = now.M[0][i-1]; for(i=1; i<4; i++) nex.M[1][i] = now.M[1][i-1]; }else{ for(i=0; i<2; i++) nex.M[i][0]=now.M[i][0], nex.M[i][3]=now.M[i][3]; nex.M[0][1]=now.M[1][1], nex.M[0][2]=now.M[0][1]; nex.M[1][1]=now.M[1][2], nex.M[1][2]=now.M[0][2]; } } bool Judge(Node node){ int i, j; for(i=0; i<2; i++){ for(j=0; j<4; j++) if(node.M[i][j] != des[i][j]) return false; } return true; } string getStr(Node node){ int i; string str; for(i=0; i<4; i++) str += (node.M[0][i] + ‘0‘); for(i=0; i<4; i++) str += (node.M[1][i] + ‘0‘); return str; } string BFS(){ string str; int i, len; now.s = ""; for(i=0; i<4; i++) now.M[0][i] = i+1; now.M[1][0]=8, now.M[1][1]=7, now.M[1][2]=6, now.M[1][3]=5; queue<Node> q; if(Judge(now)) return now.s; q.push(now); mp[getStr(now)] = true; while(!q.empty()){ now = q.front(); q.pop(); for(i=0; i<3; i++){ nex.s = now.s + op[i]; getMatrix(op[i]); if(Judge(nex)) return nex.s; str = getStr(nex); if(!mp[str]){ q.push(nex); mp[str] = true; } } } return ""; } int main(){ int i; string ans; while(cin>>des[0][0]>>des[0][1]>>des[0][2]>>des[0][3]){ //输入第一组 cin>>des[1][3]>>des[1][2]>>des[1][1]>>des[1][0]; //输入第二组 mp.clear(); ans = BFS(); printf("%d\n", ans.size()); for(i=0; i<ans.size(); i++) printf("%c", ans[i]); printf("\n"); } return 0; }
总结:这题和上一题其实大同小异,唯一不同的是,这里需要记录出现的状态,否则某些情况会出现死循环从而造成超时。但是,我想吐槽,这题干的描述真的不怎样,尤其是输出!
原文:https://www.cnblogs.com/heyour/p/12674467.html