剪邮票如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。
分析:i1、i2、i3、i4和i5为枚举要剪下的5个数,对这五个数构成的连通性进行dfs判断,如果dfs后测得从i1出发从上下左右四个方向上深度优先搜索遍历为i2~i5之间的所有点,cnt标记i5能够走到的是i1~i5这些点的个数,如果cnt == 5就说明是连在一起的,注意从4和8向右行走走不到5和9,并且从5和9出发向左行走走不到4和8~所以遇到index == 4或者index == 8并且是向右走的时候continue~(index == 5和9并向左走同理~)将result加一~累加得到的result就是结果116~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include <iostream> using namespace std; int dis[4] = {-1, 1, -4, 4}, visit[13]; int i1, i2, i3, i4, i5, cnt, result = 0; void dfs(int index) { if (cnt >= 5) return; for (int i = 0; i < 4; i++) { if ((dis[i] == 1 && (index == 4 || index == 8)) || (dis[i] == -1 && (index == 5 || index == 9))) continue; int t = index + dis[i]; if (t >= 1 && t <= 12 && visit[t] == 0 && (t == i2 || t == i3 || t == i4 || t == i5)) { visit[t] = 1; cnt++; dfs(t); } } } int main() { for (i1 = 1; i1 <= 12 - 4; i1++) { for (i2 = i1 + 1; i2 <= 12 - 3; i2++) { for (i3 = i2 + 1; i3 <= 12 - 2; i3++) { for (i4 = i3 + 1; i4 <= 12 - 1; i4++) { for (i5 = i4 + 1; i5 <= 12; i5++) { memset(visit, 0, sizeof(visit)); cnt = 1; dfs(i1); if (cnt == 5) result++; } } } } } cout << result; return 0; } |
❤ 点击这里 -> 订阅《PAT | 蓝桥 | LeetCode学习路径 & 刷题经验》by 柳婼