切換
舊版
前往
大廳
主題

ZeroJudge - c268: 簡單的三角形 解題心得

Not In My Back Yard | 2019-02-23 23:40:29 | 巴幣 0 | 人氣 403

題目連結:


題目大意:
給定一正整數 T (T ≦ 5),代表接下來有 T 個測試資料。

每個測試資料的第一列給定一正整數 n (1 ≦ n ≦ 5 × 10 ^ 7),代表有 n 個磁鐵條。第二列有 n 個正整數,分別代表那 n 個磁鐵條的長度(最大不超過10 ^ 9)。

求是否能從這 n 根磁鐵條之中挑出三條組成一個三角形。可以的話,輸出「YES」;反之,輸出「NO」。


範例輸入:
3
3
3 4 5
4
1 5 10 20
3
10 10 10


範例輸出:
YES
NO
YES


解題思維:
我們觀察以下的 n 值:
當 n = 3 ,數字最小、且不能組成三角形的數列為 1、1、2
當 n = 4 ,數字最小、且不能組成三角形的數列為 1、1、2 、3
當 n = 5 ,數字最小、且不能組成三角形的數列為 1、1、2 、3、5
當 n = 6 ,數字最小、且不能組成三角形的數列為 1、1、2 、3、5、8
當 n = 7 ,數字最小、且不能組成三角形的數列為 1、1、2 、3、5、8、13
……由上的趨勢,我們可以看出不能組成三角形的最小數列之規律正是費氏數列。

而費氏數列以指數成長,當 n = 46 時,數列最後一項為 1134903170。但是題目保證給定的磁鐵條長度 < 10 ^ 9,所以當 n > 45 時,保證可以從中挑出三個組成三角形(畢竟最小的情況已經超出範圍,也就不會有更大的情況發生)。

而剩下的 n ≦ 45 的情況,就可以直接窮舉所有的匹配可能性(Cn 取 3,也就是從 n 個物品中挑 3 個)。占用的時間並不長,可以安心去檢查是否有哪三個可以組成三角形。

而三角形組成的充分必要條件就是:兩個較短邊邊長之和 > 第三邊的邊長。所以我們可以先將其排序,方便判斷(不用判斷孰大孰小)。



但是,因為題目給定的資料量實在太大(至少 > 10MB),所以要採取輸出輸入的最佳化。最佳化方式可以參見這裡。而 n > 45 時緊接著輸入的 n 個數字,可以使用
cin.ignore(1e9, '\n')
來快速忽略掉。以上語法意為:忽略掉 10 ^ 9 個字元,除非遇上了換行(此時就會跳出這個用來忽略字元的函式)。

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

創作回應

胖胖貓
少一行 cin>>ws ,從 AC 變成 71%
好像是其中極限測資會出現在每筆測資中的#3或#4
直接 cin.ignore(1e9,'\n') 好像會直接把後面全部讀完直接 END = =
2019-02-24 00:45:04
Not In My Back Yard
是的,因為每當輸入完 n 之後就有一個換行符號('\n'),所以直接接著 cin.ignore() 是不太行的。

感謝補充。
2019-02-24 11:14:29

更多創作