剪邮票 2016蓝桥杯C++题解

剪邮票 2016蓝桥杯C++题解

资源约定: 峰值内存消耗(含虚拟机) < 256M CPU消耗 < 1000ms

描述在这里插入图片描述

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

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

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

注意

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include
不能通过工程设置而省略常用头文件。

提交程序时,注意选择所期望的语言类型和编译器类型。

答案

116

思路

先dfs枚举每一种裁剪方式,然后检查是否符合要求,若符合则ans++

检查时用bfs输出相邻的一大块又多少小块,若为5则符合要求,否则剪出的邮票就不是一整块(可能有很多小块不相邻)

写的有点复杂。。。但思路很清晰

代码

#include <iostream>
#include <algorithm>
#include <queue>
#define _for(i, a) for(int i = 0; i < (a); i++)
#define _rep(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;
bool a[3][4] = { 0 };
int ans = 0;
struct poi { int x, y; };
int dir[4][2] = {
	{0, 1}, {1, 0}, {0, -1}, {-1, 0}
};

int bfs(int i, int j) {
	int t = 0;
	queue<poi> que;
	bool b[3][4] = { 0 };
	b[i][j] = 1;
	poi tem; tem.x = i; tem.y = j;
	que.push(tem);
	while (que.size()) {
		poi c = que.front(); que.pop();
		t++;
		_for(k, 4) {
			tem.x = c.x + dir[k][0];
			tem.y = c.y + dir[k][1];
			if (tem.x >= 0 && tem.x <= 2 && tem.y >= 0 && tem.y <= 3 && a[tem.x][tem.y] == 1 && b[tem.x][tem.y] == 0) {
				que.push(tem);
				b[tem.x][tem.y] = 1;
			}
		}
	}
	return t;
}
bool che() {
	_for(i, 3) {
		_for(j, 4) {
			if (a[i][j] == 1) {
				return (bfs(i, j) == 5);
			}
		}
	}
}
void dfs(int i, int j, int m) {
	if (j >= 4) { i++; j = 0; }
	if (i >= 3) {
		if (m == 0 && che())
			ans++;
		return;
	}
	dfs(i, j + 1, m);
	if (m > 0) {
		a[i][j] = 1;
		dfs(i, j + 1, m - 1);
		a[i][j] = 0;
	}
}
int main() {
	dfs(0, 0, 5);
	cout << ans << '\n';
	return 0;
}


题目不难,但改了一天的BUG。。。
本人也是新手,也是在学习中,勿喷

转载请注明出处

欢迎有问题的小伙伴一起交流哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值