蓝桥杯——剪邮票(2016JavaB组第10题)

剪邮票(16JavaB10)

如【图1】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2】,【图3】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

问题分析

按题目,从1开始计数的话:
|-同行:(id-1)÷4的结果相等,左右邻:相减±1
|-同列:%4的结果相等,上下邻:相减±4

使用深度优先遍历,

深度优先:推进到底,触底再回

比如:{3,5,6,7,10}

先查找3跟{3,5,6,7,10}的谁相邻:
3-X
5-X
6-X
7-OK
10-等待

3-7匹配上了,继续推进,比较7和谁相邻(3已经比过了,算不匹配):
3-X
5-X
6-OK
7-等待
10-等待

7-6匹配上了,继续推进,比较6和谁相邻:
3-X
5-OK
6-等待
7-等待
10-等待

虽然6和10页相邻,但是”深度优先”,先推进下去,不管10。
5没有再相邻的,所以回到6,再匹配到10。

深度递归:
|-先推进到底,走不通了再回头
|-只要每个点都能走到,说明是连着的

package bb;
import java.util.HashSet;
import java.util.Set;
public class 剪邮票 {
	private static boolean check(int a[]) {
		boolean flag[] = new boolean[5];
		dfs(a, flag, 0);
		return flag[0] && flag[1] && flag[2] && flag[3] && flag[4];
	}
	// 深度优先搜索
	private static void dfs(int a[], boolean[] flag, int n) {
		flag[n] = true;
		for (int i = 0; i < 5; i++) {
			// 同行:(id-1)÷4的结果相等,左右邻:加减为1
			// 不能用÷5,一行就4个(9÷5==1,10÷5==2)
			if (!flag[i] && ((a[i] - 1) / 4 == (a[n] - 1) / 4)
					&& (a[i] == a[n] - 1 || a[i] == a[n] + 1)) {
				dfs(a, flag, i);
			}
			// 同列:%4的结果相等,上下邻:加减为4
			if (!flag[i] && (a[i] % 4 == a[n] % 4) && (a[i] == a[n] - 4 || a[i] == a[n] + 4)) {
				dfs(a, flag, i);
			}
		}
	}
	static Set<String> cutStamps() {
		int[] a = new int[5];
		Set<String> _set = new HashSet<String>();
		int START = 0 + 1;
		int END = 12 + 1;
		for (a[0] = START; a[0] < END; ++a[0]) {
			for (a[1] = a[0] + 1; a[1] < END; ++a[1]) {
				for (a[2] = a[1] + 1; a[2] < END; ++a[2]) {
					for (a[3] = a[2] + 1; a[3] < END; ++a[3]) {
						for (a[4] = a[3] + 1; a[4] < END; ++a[4]) {
							if (check(a)) {
								_set.add("" + a[0] + " " + a[1] + " " + a[2] + " " + a[3] + " "
										+ a[4]);
							}
						}
					}
				}
			}
		}
		return _set;
	}
	public static void main(String[] args) {
		Set<String> _set1 = cutStamps();
		System.out.println(_set1.size());
		System.out.println(_set1.contains("2 6 7 11 12"));
		System.out.println(_set1.contains("3 5 6 7 10"));
	}
}
posted @ 2019-07-15 19:35  虎老狮  阅读(358)  评论(0编辑  收藏  举报