1. 程式人生 > 其它 >藍橋杯每日一題(28)七段碼(python)

藍橋杯每日一題(28)七段碼(python)

技術標籤:python藍橋杯python列表演算法numpy藍橋杯

Topic

試題 D: 七段碼
本題總分:10 分

【問題描述】

小藍要用七段碼數碼管來表示一種特殊的文字。
上圖給出了七段碼數碼管的一個圖示
數碼管中一共有 7 段可以發光的二極體,分別標記為 a, b, c, d, e, f, g。
小藍要選擇一部分二極體(至少要有一個)發光來表達字元。
在設計字元的表達時,要求所有發光的二極體是連成一片的。
例如:b 發光,其他二極體不發光可以用來表達一種字元。
例如:c 發光,其他二極體不發光可以用來表達一種字元。
這種方案與上一行的方案可以用來表示不同的字元,儘管看上去比較相似。

例如:a, b, c, d, e 發光,f, g 不發光可以用來表達一種字元。
例如:b, f 發光,其他二極體不發光則不能用來表達一種字元,因為發光的二極體沒有連成一片。
請問,小藍可以用七段碼數碼管表達多少種不同的字元?
在這裡插入圖片描述

【答案提交】

這是一道結果填空的題
你只需要算出結果後提交即可
本題的結果為一個整數
在提交答案時只填寫這個整數
填寫多餘的內容將無法得分

Solution

這是一道需要判斷連通的問題
那麼我們就會很自然的想到運用並查集解題
能夠運用連通分量個數判斷是否滿足條件
這裡運用到了並查集列表法模板

記錄連線關係

那麼首先我們需要表示出二極體和兩個二極體間的關係:

我們可以用0到6表示七個二極體

用7 * 7的矩陣記錄與其相連的管兒
先運用numpy下的zeros設定一個7 * 7的全是0的矩陣
將每一行表示為一個管兒
接著將與其相連的管兒對應的索引變為1
那麼我們就記錄了二極體間的對應連線關係

排列二極體

二極體表示數字有1個管兒發光到7個管兒發光七種選擇
那麼我們先將二極體(0到6)放置在num中
遇到需要拿取的管道我們再拿取

之後我們從1個管兒到7個管兒開始拿取
在取用管道時我們需要將其取用的方法進行全排列
這裡用到combination隨機無放回抽樣
保證這樣點亮沒有重複

判斷是否滿足條件

在取用時我們每次例項化一個7個節點的並查集

對於每一個取用的二極體
都需要將其與臨近且點亮的二極體進行節點合併

在這裡我們先取用相應個數的二極體
之後逐個二極體判斷與其臨近的二極體是否被取用(點亮)
如果被點亮則將這兩個節點進行合併

合併之前一定要保證兩個節點的索引都是整數的形式
否則並查集列表索引會報錯

每連線一次會減少一個連通分量
被取用(點亮)的二極體若能滿足條件
就會形成一個連通分量

初始有7個連通分量
減去被點亮的二極體個數加上新形成的連通分量數1
則剩下的就是滿足條件的連通分量個數

以上所有篩選條件都滿足後res的值加一
最後輸出res的值就是所求

Code

import numpy as np
import itertools as it


class UnionFind:
    def __init__(self, n):
        self.father = list(range(n))
        self.size = [1] * n
        # 當前連通分量數目
        self.setCount = n

    def find(self, x):
        if self.father[x] == x:
            return x
        self.father[x] = self.find(self.father[x])
        return self.father[x]

    def merge(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return False
        if self.size[x] < self.size[y]:
            x, y = y, x
        self.father[y] = x
        self.size[x] += self.size[y]
        self.setCount -= 1
        return True
    

res = 0
data = list(np.zeros((7, 7)))

data[0][1] = data[0][5] = 1
data[1][0] = data[1][6] = data[1][2] = 1
data[2][1] = data[2][3] = data[2][6] = 1
data[3][2] = data[3][4] = 1
data[4][3] = data[4][5] = data[4][6] = 1
data[5][0] = data[5][4] = data[5][6] = 1

num = [i for i in range(0, 7)]

for i in range(1, 8):
    total = it.combinations(num, i)
    for j in total:
        uf = UnionFind(7)

        for z in j:
            for k in range(len(data[z])):
                z = int(z)
                b = int(data[z][k])
                if b == 1 and k in j:
                    uf.merge(z, k)

        if uf.setCount == 7 - len(j) + 1:
            res += 1

print(res)

Answer

80