蓝桥杯 剪邮票

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

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

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

蓝桥杯 剪邮票_第1张图片蓝桥杯 剪邮票_第2张图片蓝桥杯 剪邮票_第3张图片

思路
用五个for循环嵌套找到五个数的组合,从第一个数开始遍历,经过上下左右操作检测5个数是否满足相邻条件,如果5个数都可以遍历到则种类+1。
但是有个问题,在图中,向上为-4,向下为+4,向左为-1,向右为+1,如果遇到3,4,5,7,8这种情况,4+1=5,但4和5不相邻,我参考了另一篇博
客,按照这位博主的思路,将原图重构了下,真的觉得很妙哇,这样,向上为-5,向下为+5,向左为-1,向右为+1,避免了每行最后一个+1后
等于下一行第一个的情况。

蓝桥杯 剪邮票_第4张图片

原博主链接 https://blog.csdn.net/u014552756/article/details/50946197

博主写的c++,我按照他的思路写了一份Java版本的

public class Main{
	static int stamp[] = {1,2,3,4,6,7,8,9,11,12,13,14};
	static int[] aa = new int[5];
	static boolean[] vis =new boolean[5];
	static int sum=0;
	static int conn[] = {-1,1,-5,5};		//用来进行上下左右操作
	
	
	private static void dfs(int n) {
		for (int i = 0; i < 4; i++) {
			int t = aa[n] + conn[i];
			if ( t < 1 || t > 14 || t == 5 || t == 10 ) continue;	
			for (int j = 0; j < 5; j++) {
				if (!vis[j]&&aa[j]==t) {	//不为vis不为true且进行的上下左右操作后可以到达某个相邻的数
					vis[j] = true;
					dfs(j);	
				}
			}	
		}
	}
	
	public static void main(String[] args) {
		for(int a = 0 ; a < 12 ; a++)	//这里写五层循环列出所有五个数的组合
			for(int b = a+1 ; b < 12; b++)
				for (int c = b+1 ; c < 12; c++) 
					for (int d = c+1 ; d < 12; d++) 
						for (int e = d+1 ; e < 12; e++) {
							aa[0] = stamp[a];
							aa[1] = stamp[b];
							aa[2] = stamp[c];
							aa[3] = stamp[d];
							aa[4] = stamp[e];
							for (int i=0; i < 5; i++) {
								vis[i] = false;			//初始化标记为false,即没被访问过
							}
							vis[0] = true;		//第一个标记为true
							dfs(0);			//通过递归去遍历
							boolean flag = true;
							for (int i = 0; i < 5; i++) {
								if (!vis[i]) {
									flag = false;	//五个数之间存在没被连通
									break;		
								}
							}
							if (!flag) continue;	//不连通,直接继续下一个数检验
							else sum++;			//连通,种类加一
							//继续下一个数的循环和遍历访问,如一开始为1,2,3,4,6,则进入循环的下一个自增数对1,2,3,4,7检验
						}
		System.out.println(sum);
	}


}

你可能感兴趣的:(蓝桥杯)