Sticks(poj1011 藍橋杯訓練)

2021-10-04 02:25:46 字數 2476 閱讀 6760

這個剪枝簡直了,做了幾次資料不強的類似的題,想都沒想直接用之前的方法,瘋狂超時,心態**,還是看了別人**,發現遠不止我想的那麼簡單。

還是too young too ******

進入正題,這是乙個要還原樹枝的題目(題面)。我們可以理解為,把給出的所有數字序列

\,s_...s_\}

中的數任意不重複地組合成若干個數,不限制組合成的數的個數,但要求它們都為同乙個值sum

sumsu

m,求滿足要求的sum

sumsu

m最小值。

這樣沒有規律的組合的情況,最方便的解法就是——dfs.

我們怎麼去利用dfs,解決這個問題呢?

dfs要有明確的限制(退出條件),這道的題目的限制籠統的說就是——將所有陣列合成若干個和相等的組合。但是組合的數量和組合的和的大小都未知,無法開始搜尋。但是我們很顯然地看出兩者相關聯——組合和的大小*組合數量=題目數字序列的和。最簡單的就是限制組合和sum

sumsu

m的大小,然後再去搜尋。

那麼就有乙個思路了,遍歷所有可能的組合的和(sum

sumsu

m),去搜尋出乙個合理的組合方式。至少存在的乙個組合方式的最小的組合的和sum

sumsu

m的值即為答案。

我們對於每個確定的sum定義搜尋函式dfs

int

dfs(

int a,

int b,

int c,

int d)

函式內部實現時,

很多不必要的搜尋要像剪樹枝一樣把它剪掉。

1)對於每乙個要選取的加入的當前組合的數的判斷,如果都從整個序列的頭部開始遍歷那麼也浪費時間了,我們也可以適當剪枝。

2)當乙個數不能加入當前組合,那麼和它相等的數也不能加入,這可能的遍歷些也得剪掉。

3)當乙個數不能參與和其他數組合出sum時,整個sum的搜尋全部停止,剪掉。

等很多操作都可以剪枝優化。

幫助我們實現剪枝優化操作的一部分——排序,降序排序。

sort

(a+1

,a+1

+n,greater<

int>()

);

直接給出dfs**分析:

int

dfs(

int nowl,

int pos,

int hvd,

int l)

b[i]=0

;return0;

///當剩餘的數存在不能組合成和為sum的組合

}else

if(a[i]

+nowl < l)

b[i]=0

;if(nowl==0)

return0;

//關鍵剪枝

//上面這個操作當nowl==0說明,

//a[i]是作為某個組合中第一項要加入組合,

//a[i]+nowl < l&&dfs(a[i]+nowl,i+1,hvd,l)=0說明,

//a[i]不能加入當前組合。

//綜合來看a[i]無法加入乙個空的組合

//無法加入乙個空的組合,說明a[i]法加入組合,於是返回0

for(

;a[i]

==a[i+1]

&&i+

1<=n;i++);

//a[i]加不進去,和a[i]相等的都加不進去,剪掉}}

}return0;

//不存在滿足地退出

}

這應該可以整明白了昂。

來個完整**:

#include

#include

using

namespace std;

const

int maxn =

1e4+5;

int a[maxn]

,n,num;

bool b[maxn]

;int

dfs(

int nowl,

int pos,

int hvd,

int l)

b[i]=0

;return0;

}else

if(a[i]

+nowl < l)

b[i]=0

;if(nowl==0)

return0;

for(

;a[i]

==a[i+1]

&&i+

1<=n;i++);

}}}return0;

}void

solve()

sort

(a+1

,a+1

+n,greater<

int>()

);for(

int i = a[1]

;i <= sum;i++)}

}}intmain()

棍子Sticks(poj 1011) 經典搜尋

題意描述 george用相同的長度棍子,將他們隨機切成最多64個單位的長度,現在,他想回到原來的狀態,但他忘了他原來的多少根,以及他們原本是多長。請幫助他和設計乙個程式,計算最小的可能的原始長度。所有長度均大於零的整數。輸入 輸入包含2行的塊。第一行 切成多少根,最多有64根。第二行切成的每一根的長...

動態規劃1011

problem description 有乙隻經過訓練的蜜蜂只能爬向右側相鄰的蜂房,不能反向爬行。請程式設計計算蜜蜂從蜂房a爬到蜂房b的可能路線數。其中,蜂房的結構如下所示。input 輸入資料的第一行是乙個整數n,表示測試例項的個數,然後是n 行資料,每行包含兩個整數a和b 0 output 對於...

10 11學習總結

現在補10.11的坑,假裝現在是10.11。今天繼續補lch講的動規的坑,學習了線性動規與區間動規,至於樹剖以後再補坑。1.線性動規 此處拓展到兩個比較重要的演算法 1 lcs最長公共子串行.狀態轉移方程為 f 1 1 0 f i j f i 1 j 1 1 x y f i j max f i 1 ...