Blue Bridge Cup previous exam questions nine palaces rearrangement

Problem Description

  For example, in the nine-square grid in the first picture below, there are number cards from 1 to 8, and one grid is empty. Cards in the cells adjacent to the blank cells can be moved into the blank cells. After several moves, the situation shown in the second diagram can be formed.

       We record the position of the first picture as: 12345678. The situation of
  the second picture is recorded as: 123.46758.
  Obviously, the numbers are recorded in the order from top to bottom and left to right, and spaces are recorded as periods.
  The task of this problem is to know the initial state and final state of the nine palaces, and find the minimum number of steps that can be reached. If it cannot be reached no matter how many steps, output -1.

input format

  Enter the first line containing the initial state of the Nine Houses and the second line containing the final state of the Nine Houses.

output format

  Output the minimum number of steps, or -1 if no solution exists.

sample input

12345678.
123.46758

Sample output

3

sample input

13524678.
46758123.

Sample output

22

// 双广搜(起始位置分别为始态和终态)+康拓展开排重
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;
 
public class Main {
 
	// 被访问过的为始态到该状态所需要的步数,未被访问过的为-1
	static int[] state1 = new int[362880];
	// 被访问过的为终态到该状态所需要的步数,未被访问过的为-1
	static int[] state2 = new int[362880];
	// 四行,分别表示空白格向上、下、左、右四个方向走
	static int[][] dir = { { 1, 0 }, { -1, 0 }, { 0, -1 }, { 0, 1 } };
 
	public static void main(String[] args) {
		Arrays.fill(state1, -1);
		Arrays.fill(state2, -1);
		Scanner sc = new Scanner(System.in);
		String start = sc.nextLine();
		String end = sc.nextLine();
		int ans = bfs(start, end);
		System.out.println(ans);
		sc.close();
	}
 
	public static int bfs(String start, String end) {
		LinkedList<Run> list1 = new LinkedList<Run>();
		LinkedList<Run> list2 = new LinkedList<Run>();
		list1.add(new Run(start, 0));
		list2.add(new Run(end, 0));
 
		while (!list1.isEmpty()) {
			Run head1 = list1.get(0);
			list1.remove(0);
			Run head2 = list2.get(0);
			list2.remove(0);
 
			int step1 = head1.step;
			if (head1.str.equals(end)) {
				return step1;
			}
			int step2 = head2.step;
			if (head2.str.equals(start)) {
				return step2;
			}
 
			char[][] ch1 = stringToArr(head1.str);
			int pointIndex1 = head1.str.indexOf('.');
			int pointX1 = pointIndex1 / 3;
			int pointY1 = pointIndex1 % 3;
			char[][] ch2 = stringToArr(head2.str);
			int pointIndex2 = head2.str.indexOf('.');
			int pointX2 = pointIndex2 / 3;
			int pointY2 = pointIndex2 % 3;
 
			for (int i = 0; i < dir.length; i++) {
				int nextX1 = pointX1 + dir[i][0];
				int nextY1 = pointY1 + dir[i][1];
				int nextX2 = pointX2 + dir[i][0];
				int nextY2 = pointY2 + dir[i][1];
 
				if (nextX1 >= 0 && nextX1 <= 2 && nextY1 >= 0 && nextY1 <= 2) {
					{
						char temp = ch1[pointX1][pointY1];
						ch1[pointX1][pointY1] = ch1[nextX1][nextY1];
						ch1[nextX1][nextY1] = temp;
					}
					String s = arrToString(ch1);
 
					if (state1[kangtuo(s)] == -1) {
						list1.addLast(new Run(s, step1 + 1));
						state1[kangtuo(s)] = step1 + 1;
					}
					if (state2[kangtuo(s)] != -1) {
						return step1 + 1 + state2[kangtuo(s)];
					}
					{
						char temp = ch1[pointX1][pointY1];
						ch1[pointX1][pointY1] = ch1[nextX1][nextY1];
						ch1[nextX1][nextY1] = temp;
					}
				}
 
				if (nextX2 >= 0 && nextX2 <= 2 && nextY2 >= 0 && nextY2 <= 2) {
					{
						char temp = ch2[pointX2][pointY2];
						ch2[pointX2][pointY2] = ch2[nextX2][nextY2];
						ch2[nextX2][nextY2] = temp;
					}
					String s = arrToString(ch2);
 
					if (state2[kangtuo(s)] == -1) {
						list2.addLast(new Run(s, step2 + 1));
						state2[kangtuo(s)] = step2 + 1;
					}
					if (state1[kangtuo(s)] != -1) {
						return step2 + 1 + state2[kangtuo(s)];
					}
					{
						char temp = ch2[pointX2][pointY2];
						ch2[pointX2][pointY2] = ch2[nextX2][nextY2];
						ch2[nextX2][nextY2] = temp;
					}
				}
			}
		}
		return -1;
	}
 
	// 康拓展开判重
	public static int kangtuo(String str) {
		int len = str.length();
		// 0~8的阶乘
		int[] fac = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320 };
		// 存放由康拓展开计算出来的序数
		int sum = 0;
		int num = 0;
		for (int i = 0; i < len; i++) {
			num = 0;
			for (int j = i + 1; j < len; j++) {
				if (str.charAt(j) - '0' < str.charAt(i) - '0')
					num++;
			}
			sum += num * fac[len - 1 - i];
		}
		return sum;
	}
 
	// 将字符串转为二维数组
	public static char[][] stringToArr(String str) {
		char[][] a = new char[3][3];
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				a[i][j] = str.charAt(i * 3 + j);
			}
		}
		return a;
	}
 
	// 将二维数组转为字符串
	public static String arrToString(char[][] a) {
		String s = "";
		for (int i = 0; i < a.length; i++) {
			s += new String(a[i]);
		}
		return s;
	}
 
}
 
// 他的实例存放着两个属性,一个String表示当前状态,一个step表示走到这个状态需要几步
class Run {
	String str;
	int step;
 
	public Run(String str, int step) {
		this.str = str;
		this.step = step;
	}
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326141548&siteId=291194637