第十四屆藍橋杯大賽軟體賽省賽Python 《三國遊戲》

Nhwite發表於2024-03-21

問題描述


問題型別

排序,貪心演算法。

問題分析

當第i個事件發生時會分別讓X,Y,Z增加Ai,Bi,Ci

即當某個事件發生時,三國各增加士兵數Ai,Bi,Ci。

如果X,Y,Z的其中一個大於另外兩個之和,我們認為其獲勝。

即當n個事件都確定了是否會發生後,存在X,Y,Z中任一大於另外兩個之和,則有其中一個國家獲勝。由於n個事件都有發生與不發生兩種情況,所以最終的結果有2^n種情況,如果所有的情況都不能決出勝負,則輸出-1;否則,在所有能夠決出勝負的情況中選擇事件發生數最多的。

由輸入和輸出格式知,輸入第二行至第四行表示按照順序每一次事件若發生(可能不發生)則增加的國家士兵數量,所以輸入的第二至四行每一列表示各國在某一次事件發生時增加計程車兵數量。

問題簡化

由於各事件獨立,不需要考慮事件發生的順序,只需考慮事件最終發生與否。

貪心演算法(又稱貪婪演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,演算法得到的是在某種意義上的區域性最優解 。在這個問題中,所要求的「最好選擇」就是找出事件發生數最多的,如何才能讓事件發生數達到最多呢?

假設X國獲勝,那麼在每一次事件發生時,我們總是選擇X國與Y國和Z國士兵增加數量之差儘量大,即A[i] - (B[i] + C[i])儘量大,當事件數增加到X - (Y + Z) > 0(保證X國能獲勝)時,事件數達到最大。對於另外兩個國家同理。最終找出三國最終獲勝的所有情況中事件發生數能夠達到最大的即可。
如果所有情況都無法滿足某一國能夠獲勝,即所有事件不論最終發生與否,都無法決出勝負,則輸出-1。

程式碼實現

n = int(input())
X = list(map(int, input().split()))
Y = list(map(int, input().split()))
Z = list(map(int, input().split()))


def maxEventsnum(X, Y, Z, count=n):
    max = []  #每一次事件X國士兵增加數與其他兩國士兵增加數之和的差的結果列表
    temp = 0  #士兵數之差
    j = 0  #事件發生數
    for i in range(0, n):
        max.append(X[i] - Y[i] - Z[i])
    max = sorted(max)  #對max進行排序,從大到小依次新增,直至最後一個temp仍大於零
    while count:
        count -= 1
        if temp + max[count] <= 0:
            if count == n - 1:
                j = -1
            break  #出現再使一個事件發生時必然無法獲勝,則跳出迴圈
        else:
            j += 1
            temp += max[count]
    return j  #最大事件發生數


ans = max([maxEventsnum(X, Y, Z), maxEventsnum(Y, X, Z), maxEventsnum(Z, X, Y)])
print(ans)

相關文章