Acwing1107. 魔板(Java题解)
2026/4/9大约 3 分钟
Acwing1107. 魔板(Java题解)
Rubik 先生在发明了风靡全球的魔方之后,又发明了它的二维版本——魔板。
这是一张有 8 个大小相同的格子的魔板:
1 2 3 4
8 7 6 5我们知道魔板的每一个方格都有一种颜色。
这 种颜色用前 8个正整数来表示。
可以用颜色的序列来表示一种魔板状态,规定从魔板的左上角开始,沿顺时针方向依次取出整数,构成一个颜色序列。
对于上图的魔板状态,我们用序列 (1,2,3,4,5,6,7,8)来表示,这是基本状态。
这里提供三种基本操作,分别用大写字母 A,B,C 来表示(可以通过这些操作改变魔板的状态):
A:交换上下两行;
B:将最右边的一列插入到最左边;
C:魔板中央对的4个数作顺时针旋转。
下面是对基本状态进行操作的示范:
A:
8 7 6 5
1 2 3 4B:
4 1 2 3
5 8 7 6C:
1 7 2 4
8 6 3 5对于每种可能的状态,这三种基本操作都可以使用。
你要编程计算用最少的基本操作完成基本状态到特殊状态的转换,输出基本操作序列。
注意:数据保证一定有解。
输入格式
输入仅一行,包括 88 个整数,用空格分开,表示目标状态。
输出格式
输出文件的第一行包括一个整数,表示最短操作序列的长度。
如果操作序列的长度大于0,则在第二行输出字典序最小的操作序列。
数据范围
输入数据中的所有数字均为 11 到 88 之间的整数。
输入样例:
2 6 8 4 5 7 3 1输出样例:
7
BCABCCB思路
让我们看一下一维对应的3个操作
把初始字符串s存为 "12345678"
A操作相当于把s翻转 ,即为”87654321“
B操作相当于把4放在s开头,5放在s结尾
C操作与二维的思路相同,都是对应位置上的字符相互替换
Java代码
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;
/**
* https://www.acwing.com/problem/content/description/1109/
*/
public class Main {
static class Pair{
char c;
String s;
public Pair(char c, String s) {
this.c = c;
this.s = s;
}
}
static Scanner sc = new Scanner(System.in);
static HashMap<String,Pair> pr = new HashMap<>();
static HashMap<String,Integer> dist = new HashMap<>();
static String start,end;
static void bfs(){
ArrayDeque<String>q = new ArrayDeque<>();
q.add(start);
while (!q.isEmpty()){
String t = q.poll();
if (t.equals(end)){
return;
}
String[]save = new String[3];
StringBuilder u = new StringBuilder(t);
save[0] = String.valueOf(u.reverse());
save[1] = t.charAt(3)+t.substring(0,3)+t.substring(5)+t.charAt(4);
char[]temp = t.toCharArray();
temp[1] = t.charAt(6);temp[2] = t.charAt(1);temp[5] = t.charAt(2);temp[6] = t.charAt(5);
save[2] = String.valueOf(temp);
for(int i = 0; i <3; i++) {
if (!dist.containsKey(save[i])||dist.get(save[i]) == 0) {
dist.put(save[i], dist.getOrDefault(t,0)+1);
pr.put(save[i],new Pair((char) (i+'A'),t));
if (save[i].equals(end)){
break;
}
q.add(save[i]);
}
}
}
}
public static void main(String[] args) {
start = "12345678";
char[]p = new char[8];
for(int i = 0; i <8; i++) {
p[i] = (char) (sc.nextInt()+'0');
}
end = String.valueOf(p);
bfs();
System.out.println(dist.get(end)==null?0:dist.get(end));
StringBuilder res = new StringBuilder();
if (dist.containsKey(end) && dist.get(end) != 0) {
while (!end.equals(start)){
res.append(pr.get(end).c);
end = pr.get(end).s;
}
}
if (res.length()!=0){
System.out.println(res.reverse());
}
}
}