征战蓝桥 —— 2016年第七届 —— C/C++A组第7题——剪邮票
剪郵票
如【圖1.jpg】, 有12張連在一起的12生肖的郵票。
現(xiàn)在你要從中剪下5張來,要求必須是連著的。
(僅僅連接一個角不算相連)
比如,【圖2.jpg】,【圖3.jpg】中,粉紅色所示部分就是合格的剪取。
請你計算,一共有多少種不同的剪取方法。
請?zhí)顚懕硎痉桨笖?shù)目的整數(shù)。
注意:你提交的應(yīng)該是一個整數(shù),不要填寫任何多余的內(nèi)容或說明性文字。
Ideas
最終是想讓我們計算”一共有多少種不同的剪取方法“,所以是要搜索所有的狀態(tài)空間,應(yīng)該用DFS。
這道題其實(shí)就是從12個格子中選出來5個,保證5個格子是聯(lián)通的。
所以我們可以把問題建模:一個長度為12、元素為0的列表,從中選擇5個格子置為1,然后判斷5個1的位置對應(yīng)到矩陣上是不是連通的。
我覺得這道題的考點(diǎn)就是連通塊檢查,連通塊檢查可以定義為一個單獨(dú)的函數(shù),經(jīng)典的連通塊計算方法還是通過DFS。
對于一個矩陣,首先要定義一個變量cnt,用于統(tǒng)計矩陣中為1的元素個數(shù),然后整個遍歷一遍矩陣,找到第一個為1的位置,先把 cnt + 1,然后進(jìn)行 DFS,從當(dāng)前位置開始,四個方向擴(kuò)散,如果遇到值為1的元素,則置為0。
注意哈,此時如果所有的1是連通的,那么我從一個1出發(fā),就可以將所有的1都置為0,后面繼續(xù)遍歷矩陣就不會再遇到值為1的元素,所以最后判斷是不是連通塊就是判斷 cnt == 1。
OK,然后就可以開始寫代碼啦。
Code
C++
#include <algorithm> #include <iostream>using namespace std;int ans;bool check(int arr[12]);void dfs(int g[3][4], int i, int j);int main(int argc, const char *argv[]) {int per[] = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};do {if (check(per))ans++;} while (next_permutation(per, per + 12));cout << ans << endl;return 0; }bool check(int arr[12]) {int g[3][4];memset(g, 0, sizeof(g)); //將相應(yīng)位置標(biāo)注為1for (int i = 0; i < 3; ++i) {for (int j = 0; j < 4; ++j) {if (arr[i * 4 + j] == 1)g[i][j] = 1;}} // 經(jīng)典連通塊計算int cnt = 0;for (int i = 0; i < 3; ++i) {for (int j = 0; j < 4; ++j) {if (g[i][j] == 1) {dfs(g, i, j);cnt++;}}}return cnt == 1; }void dfs(int g[3][4], int i, int j) {g[i][j] = 0;if (i + 1 <= 2 && g[i + 1][j] == 1) dfs(g, i + 1, j);if (i - 1 >= 0 && g[i - 1][j] == 1) dfs(g, i - 1, j);if (j + 1 <= 3 && g[i][j + 1] == 1) dfs(g, i, j + 1);if (j - 1 >= 0 && g[i][j - 1] == 1) dfs(g, i, j - 1); }Python
from copy import deepcopy from itertools import permutationsdef check(m):def dfs(x, y):m[x][y] = 0for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:nx, ny = x + dx, y + dyif -1 < nx < len(m) and -1 < ny < len(m[0]) and m[nx][ny] == 1:dfs(nx, ny)cnt = 0for r in range(3):for c in range(4):if m[r][c] == 1:dfs(r, c)cnt += 1return cnt == 1if __name__ == '__main__':ans = set()state = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]matrix = [[0] * 4 for _ in range(3)]for ste in permutations(state):# 將一維狀態(tài)向量映射為二維矩陣for i in range(3):for j in range(4):matrix[i][j] = ste[i * 4 + j]string = ''.join([''.join(map(str, row)) for row in matrix])if check(deepcopy(matrix)) and string not in ans: # 連通塊檢查print(string)ans.add(string)print(len(ans))Answer: 116
總結(jié)
以上是生活随笔為你收集整理的征战蓝桥 —— 2016年第七届 —— C/C++A组第7题——剪邮票的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2016年第七届蓝桥杯 - 省赛 - C
- 下一篇: 征战蓝桥 —— 2016年第七届 ——