切換
舊版
前往
大廳
主題

ZeroJudge - c482: pF 絕對多數 解題心得

Not In My Back Yard | 2020-03-31 00:22:54 | 巴幣 0 | 人氣 363

題目連結:


題目大意:
輸入有多筆測資。每筆第一列給定一正整數 N (N ≦ 2000,N = 0 時代表輸入結束),代表有一個 N × N 的矩陣。接著有 N 列輸入,每列給定 N 個正整數 D(D < 2 ^ 31),代表這個 N × N 矩陣的內容。

接著給定一正整數 q (q ≦ 70),代表接著有 q 筆詢問,每筆佔一列。每列給定四整數 r1 、 r2 、 c1 、 c2 (0 ≦ r1 ≦ r2 < N ,0 ≦ c1 ≦ c2 < N),代表要問該矩陣第 r1 列(索引值從 0 開始)到第 r2 列且第 c1 行到第 c2 行所圍起來的矩形區域裡的「絕對多數」之數字為何?如果沒有的話,輸出「-1」。

「絕對多數」的意義為:假設一團數字裡有 M 個數字(可重複出現相同的數字),其中有一個數字出現「超過」M ÷ 2 次。則該數字即是「絕對多數」的數字。



範例輸入:
5
1 2 3 3 2
2 1 1 2 3
1 2 3 1 1
0 2 3 3 1
0 3 1 3 2
2
0 1 0 2
2 4 1 3
0


範例輸出:
-1
3


解題思維:
「絕對多數」(即出現超過半數的物件)可以使用一個演算法叫做博耶—摩爾多數投票演算法(Boyer–Moore majority vote algorithm)。根據我大電神朋友的比喻,這個演算法可稱作「戰鬥」演算法,如下:
先從數字裡抓一個(通常是第一個)出來當作「衛冕者」,並設定一計數器 C 之初始值為 1 當衛冕者的「血量」。

接著掃過其他的數字(挑戰者),數字不一樣就打架,雙方扣 1 單位血(挑戰者的血量是 1 ,衛冕者是 C)。如果衛冕者的血量扣完了就抓下一個人當衛冕者;如果數字一樣的話,衛冕者就「補血」,即 C 的值 + 1 。

最後剩下的衛冕者即是「絕對多數」的數字。


但是以上的演算法是建立在數字裡保證有「絕對多數」,如果沒有上述形同虛設。所以在沒有保證絕對多數的情況下要多掃一次數字確保該數字的出現次數有超過一半。

在這題數字們是由 r1 、 r2 、 c1 、 c2 而決定出矩陣中的矩形範圍。所以就用雙重迴圈跑過該區域並套用以上演算法即可得出是否有絕對多數的數字。有就輸出該值;反之,輸出「-1」。

此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作