乙個袋子裡面有n個球,每個球上面都有乙個號碼(擁有相同號碼的球是無區別的)。如果乙個袋子是幸運的當且僅當所有球的號碼的和大於所有球的號碼的積。
例如:如果袋子裡面的球的號碼是,這個袋子就是幸運的,因為1 + 1 + 2 + 3 > 1 * 1 * 2 * 3
你可以適當從袋子裡移除一些球(可以移除0個,但是別移除完),要使移除後的袋子是幸運的。現在讓你程式設計計算一下你可以獲得的多少種不同的幸運的袋子。
輸入描述:
第一行輸入乙個正整數n(n ≤ 1000)
第二行為n個數正整數xi(xi ≤ 1000)
輸出描述:
輸出可以產生的幸運的袋子數
輸入例子:
3 1 1 1
輸出例子:
題目可以轉化成求符合條件的集合真子集個數。每次從全集中選擇若干元素(小球)組成子集(袋子)。集合子集個數為2^n個,使用dfs必然超時。且此題有重複元素,那麼就搜尋剪枝。
搜尋演算法按搜尋的方式分有兩類,一類是深度優先搜尋,一類是廣度優先搜尋。我們知道,深度搜尋程式設計簡單,程式簡潔易懂,空間需求也比較低,但是這種方法的 時間複雜度往往是指數級的,倘若不加優化,其時間效率簡直無法忍受;而廣度優先搜尋雖然時間複雜度比前者低一些,但其龐大的空間需求量又往往讓人望而卻步。
所以,對程式進行優化,就成為搜尋演算法程式設計中最關鍵的一環。本文所要討論的便是搜尋演算法中優化程式的一種基本方法叫「剪枝」。
搜尋的程序可以看作是從樹根出發,遍歷一棵倒置的樹——搜尋樹的過程。而所謂剪枝,顧名思義,就是通過某種判斷,避免一些不必要的遍歷過程,形象的說,就是剪去了搜尋樹中的某些「枝條」,故稱剪枝。應用剪枝優化的核心問題是設計剪枝判斷方法,即確定哪些枝條應當捨棄,哪些枝條應當保留的方法。
原則之一:正確性。 因為它能夠「剪去」搜尋樹中的一些「枝條」。然而,如果在剪枝的時候,將「長有」我們所需要的解的枝條也剪掉了,那麼,一切優化也就都失去了意義。所以,對剪枝的第乙個要求就是正確性,即必須保證不丟失正確的結果,這是剪枝優化的前提。我們利用「必要條件」來進行剪枝判斷。也就是說,通過解所必須具備的特徵、必須滿足的條件等方面來考察待判斷的枝條能否被剪枝。這樣,就可以保證所剪掉的枝條一定不是正解所在的枝條。
原則之二:準確性。
即能夠盡可能多的剪去不能通向正解的枝條。準確性可以說是剪枝優化的生命。
原則之三:高效性。
經常還需要提高判斷操作本身的時間效率。
綜上所述,我們可以把剪枝優化的主要原則歸結為六個字:正確、準確、高效。
我們可以把常用的剪枝判斷大致分成以下兩類:
可行性剪枝。
最優性剪枝(上下界剪枝)。
#include
#include
#include
using
namespace
std;
int dfs(vector
nums,int beg,int sum,int pi)
return res;
}int main()
int sum = 0;
int pi = 1;
cout
<0,0,1);
}
幸運的袋子
乙個袋子裡面有n個球,每個球上面都有乙個號碼 擁有相同號碼的球是無區別的 如果乙個袋子是幸運的當且僅當所有球的號碼的和大於所有球的號碼的積。例如 如果袋子裡面的球的號碼是,這個袋子就是幸運的,因為1 1 2 3 1 1 2 3 你可以適當從袋子裡移除一些球 可以移除0個,但是別移除完 要使移除後的袋...
幸運的袋子
乙個袋子裡面有n個球,每個球上面都有乙個號碼 擁有相同號碼的球是無區別的 如果乙個袋子是幸運的當且僅當所有球的號碼的和大於所有球的號碼的積。例如 如果袋子裡面的球的號碼是,這個袋子就是幸運的,因為1 1 2 3 1 1 2 3 你可以適當從袋子裡移除一些球 可以移除0個,但是別移除完 要使移除後的袋...
幸運的袋子
乙個袋子裡面有n個球,每個球上面都有乙個號碼 擁有相同號碼的球是無區別的 如果乙個袋子是幸運的當且僅當所有球的號碼的和大於所有球的號碼的積。例如 如果袋子裡面的球的號碼是,這個袋子就是幸運的,因為1 1 2 3 1 1 2 3 你可以適當從袋子裡移除一些球 可以移除0個,但是別移除完 要使移除後的袋...