剪邮票 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。。。
本人也是新手,也是在学习中,勿喷
转载请注明出处
欢迎有问题的小伙伴一起交流哦~