蓝桥杯 剪邮票

剪邮票
	如【图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后
等于下一行第一个的情况。

在这里插入图片描述

原博主链接 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);
	}


}

本题目链接:https://www.lanqiao.cn/courses/2784/exams/3864/question_sets/16435/problems/WB1/ 题目描述 现在有一个二维码,我们要把它裁成一个 n 行 m 列的小二维码。当然,裁时我们可以只截取一个小于 n 行 m 列的区域,但是这个区域必须包含原来的二维码。 现在,我们已经知道了原来的二维码的大小,以及每一个格子的黑白情况,问:是否存在一种裁方案,能够得到一个小二维码,使得这个小二维码恰好包含 k 个黑色格子? 请注意,这个二维码是以字符串形式给出的。其中,字符串中的 “1” 表示黑色格子,字符串中的 “0” 表示白色格子。字符串中的回车和空格都需要忽略。 输入格式 输入的第一行包含三个整数 n, m 和 k,分别表示原始二维码的行数、列数,以及小二维码中要求包含的黑色格子数。 输入的第二行到第 n + 1 行,每行包含一个长度为 m 的字符串,表示原始二维码。 输出格式 如果存在一种裁方案,能够得到一个小二维码,使得这个小二维码恰好包含 k 个黑色格子,则输出 Yes,否则输出 No。 样例输入1 5 5 2 00000 00100 01110 00100 00000 样例输出1 Yes 样例输入2 5 5 2 00000 00100 01110 00110 00000 样例输出2 No 数据规模与约定 对于 30% 的数据,1 <= n, m <= 10,1 <= k <= 5。 对于 60% 的数据,1 <= n, m <= 50,1 <= k <= 25。 对于 100% 的数据,1 <= n, m <= 100,1 <= k <= n * m。 时间限制:1s 空间限制:256MB 思路分析 本题目可以采用暴力枚举的方法来解决,我们可以先得到原先二维码中的黑色格子数目,然后再枚举所有的情况,看看是否有一种情况满足条件即可。 具体步骤如下: 首先,我们需要先统计一下原先二维码中的黑色格子数目,这个可以用一个计数器来实现,每当一个格子为黑色时,计数器加一即可。 接着,我们枚举裁后的小二维码的左上角位置,即枚举左上角是第 i 行第 j 列的方格,可以用两层循环来实现。 然后,我们再在这个位置上枚举所有可能的小二维码大小,即从这个位置开始向右最多可以扩展的列数为 min(m-j+1, k),向下最多可以扩展的行数为 min(n-i+1, k),从最小的大小开始,逐渐增大。 在每个大小下,我们可以统计一下小二维码中黑色格子的数目,如果恰好等于 k,那么就说明满足条件,输出 Yes,结束程序。如果一直到最大的大小都没有满足条件,那么就说明不存在这样的方案,输出 No 即可。 代码实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值