方格填数-全排列+check

蓝桥杯第七届省赛第6题

方格填数

如下的10个格子
±-±-±-+
| | | |
±-±-±-±-+
| | | | |
±-±-±-±-+
| | | |
±-±-±-+

(如果显示有问题,也可以参看【图1.jpg】)
在这里插入图片描述

填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)

一共有多少种可能的填数方案?

请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

思路:
使用全排列,将每一排列填入表格中,判断表格中的每一个元素是否满足要求

代码:

public class Main6 {

	static int[][] map = new int[3][4]; // 存储表格
	static int count; // 符合要求的方案

	public static void main(String[] args) {
		int[] arr = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

		// 第一个格子和最后一个格子为空,所以初始化为2,防止数字与其他数字相邻
		map[0][0] = -2;
		map[2][3] = -2;

		f(arr, 0);
		System.out.println(count);
	}

	// 生成全排列
	private static void f(int[] arr, int step) {
		if (step == arr.length) {
			// 往map中填入当前序列的数
			fill(arr);
			// 判断当前序列是否符合要求
			if (check()) {
				count++;
			}
		} else {
			for (int i = step; i < arr.length; i++) {
				swap(arr, step, i);
				f(arr, step + 1);
				swap(arr, step, i);
			}
		}
	}

	private static boolean check() {
		boolean flag = true;
		for (int i = 0; i < map.length; i++) {
			for (int j = 0; j < map[0].length; j++) {
				if ((i == 0 && j == 0) || (i == 2 && j == 3)) {
					continue;
				} else {
					// 判断八个方向
					if (j - 1 >= 0 && Math.abs(map[i][j - 1] - map[i][j]) == 1) {// 西
						flag = false;
						break;
					}
					if (j - 1 >= 0 && i - 1 >= 0 && Math.abs(map[i - 1][j - 1] - map[i][j]) == 1) {// 西北
						flag = false;
						break;
					}
					if (i - 1 >= 0 && Math.abs(map[i - 1][j] - map[i][j]) == 1) {// 北
						flag = false;
						break;
					}
					if (j + 1 < map[0].length && i - 1 >= 0 && Math.abs(map[i - 1][j + 1] - map[i][j]) == 1) {// 东北
						flag = false;
						break;
					}
					if (j + 1 < map[0].length && Math.abs(map[i][j + 1] - map[i][j]) == 1) {// 东
						flag = false;
						break;
					}
					if (j + 1 < map[0].length && i + 1 < map.length && Math.abs(map[i + 1][j + 1] - map[i][j]) == 1) {// 东南
						flag = false;
						break;
					}
					if (i + 1 < map.length && Math.abs(map[i + 1][j] - map[i][j]) == 1) {// 南
						flag = false;
						break;
					}
					if (j - 1 >= 0 && i + 1 < map.length && Math.abs(map[i + 1][j - 1] - map[i][j]) == 1) {// 西南
						flag = false;
						break;
					}
				}
			}
		}
		return flag;
	}

	// 往map中填入当前序列的数
	private static void fill(int[] arr) {
		int index = 0;
		for (int i = 0; i < map.length; i++) {
			for (int j = 0; j < map[0].length; j++) {
				if ((i == 0 && j == 0) || (i == 2 && j == 3)) {
					continue;
				} else {
					map[i][j] = arr[index];
					index++;
				}
			}
		}
	}

	private static void swap(int[] arr, int step, int i) {
		int temp = arr[step];
		arr[step] = arr[i];
		arr[i] = temp;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值