1. 程式人生 > >Luo2383:狗哥玩木棒 題解

Luo2383:狗哥玩木棒 題解

個數 spa 枚舉 但是 文件中 無法 over false 輸出

Problem

題目背景

狗哥又趁著語文課幹些無聊的事了...

題目描述

現給出一些木棒長度,那麽狗哥能否用給出的木棒(木棒全用完)組成一個正方形呢?

輸入輸出格式

輸入格式:

輸入文件中的第一行是一個整數n表示測試的組數,接下來n行表示每組的測試數據。 每行的第一個數為m(4<=m<=20),接下來m個數ai(1<=ai<=1000)表示木棒的長度。

輸出格式:

對於每組測試數據,如果可以組成正方形輸出“yes”,否則輸出“no”。

輸入輸出樣例

輸入樣例#1:

3
4 1 1 1 1 
5 10 20 30 40 50 
8 1 7 2 6 4 4 3 5

輸出樣例#1:

yes
no
yes

Solution

呵呵,這居然是技術分享圖片的題目,其實是一道暴搜題,相信大家都會寫。

但是,它之所以能被評為技術分享圖片是因為純粹的暴搜是無法過了這題的,需要加一些 剪枝


技術分享圖片

這是我的提交記錄,可以看到,從一開始的 TLEAC,時間差距是巨大的,甚至同樣 AC 的代碼也有 5 倍時間的差距。這都是剪枝的操作所導致的。


先來講講怎麽從 TLEAC,這是我暴搜最初的版本:

bool dfs(int t, int l1, int l2, int l3, int l4){ //t 表示當前到第幾個棍子了,l1,l2,l3,l4分別是正方形的四條邊的長度,返回值表示是否可行
    if (t == n + 1){return (l1 == l2 && l2 == l3 && l3 == l4);}
    if (dfs(t+1, l1 + a[t], l2, l3, l4)) return true;
    if (dfs(t+1, l1, l2 + a[t], l3, l4)) return true;
    if (dfs(t+1, l1, l2, l3 + a[t], l4)) return true;
    if (dfs(t+1, l1, l2, l3, l4 + a[t])) return true;
    return false;
}

這個暴搜沒有經過任何優化,我們需要考慮優化的動機。我們發現,有一些狀態是 沒有必要枚舉下去的,舉個例子,如果 \(sum = \Sigma a_i\)\(sum\) 不是 4 的倍數,那麽顯然不能拼成正方形;進一步,如果 l1,l2,l3,l4 中的某個數大於 \(sum \over 4\),顯然應該返回 false,沒有必要枚舉下去。

加了這兩個優化,代碼就 AC 了哈。


還能不能進一步優化呢?
思考剛才那個剪枝,因為剪枝肯定是越早越好,如果我們把棍子按照長度降序排列,那麽剪枝的時間肯定會有所提前。這個優化可以把時間優化到原來的 \(1 \over 5\)
至於我的那個 CE,是因為降序排序時 sort(a+1, a+1+n, greater<int>() )

寫成了 sort(a+1, a+1+n, greater<int> ),話說難道我以前都寫錯了QAQ?

Luo2383:狗哥玩木棒 題解