POJ 1011 Sticks DFS回溯剪枝

2021-06-22 07:18:19 字數 1447 閱讀 1165

poj 1011 sticks(dfs回溯剪枝)

題意:

給你n根長度可能不同的棍子,它們是由多根(或1根)長棍子切斷而成的。現在要你求出原始棍子的最小合法長度是多少?

分析:

本題是poj2362的加強版:

用類似的做法,首先我們求出所有小棍子的長度和sum.然後原始棍子的長度l肯定要》=最長的當前棍子長.

然後讓l從小到大遞增(l<=sum),一一嘗試.當sum%l==0時,可以dfs嘗試.

其中用vis[i]表示第i根棍子是否被使用了,用

bool dfs(intcur_len, int cnt, int left, int begin)來嘗試構造.其中cur_len表示本輪嘗試我們假定的原始棍長,cnt表示我們正在嘗試構造第cnt根原始棍,left表示當前第cnt棍子我們還差left長度需要構造,begin表示小棍子從begin位置的小棍子開始探索(

關鍵的剪枝就在這裡

,定序技巧,在

poj2362

我解釋了

)

源**中共有5處剪枝,少了一處都可能超時.關鍵在於剪枝4那裡,小木棍一定要從大到小排序.(從小到大排序超時) 主要原因在於:

剪枝3那裡,如果一根小木棍作為當前原始木棍的第一根都沒有後續匹配方案的話,那麼這個小木棍不可能出現在剩下的任何方案中(想想,是不是).這裡如果當前剩餘小木棍長度為1,1,1,1,1,1,8. 我們需要配對的原始木棍長度為10時,那麼就要遞迴6次才能判斷出.如果小木棍長度從大到小排序的話如:8 1 1 1 1 1 1 ,那麼只需要遞迴3次就能判斷出.所以長的小木棍收斂速度更快,所以需要木棍長度從大到小排序再dfs.

ac**:

#include#include#includeusing namespace std;

const int maxn=70;

int n,sum;

int len[maxn];

bool vis[maxn];

bool cmp(int a,int b)

bool dfs(int cnt,int cur_len,int left,int begin)//當前構造第cnt根棍子,原始長度cur_len,還需left長度每構造,從begin位置開始選小棍子

vis[i]=false;

if(left==cur_len) break;//剪枝3,此時的用len[i]的小木棍作為原始棍的第一根,

//都不能組合成一根原始棍,說明len[i]不論放**都是沒用的,後面不用再試

}return false;

}int main()

{ while(scanf("%d",&n)==1&&n)

{sum=0;

int max_len=0;

for(int i=0;i

POJ 1011 木棒問題

問題描述 喬治拿來一組等長的棍子,將它們隨機地裁斷 截斷後的小段稱為木棒 使得每一節木棒的長度都不超過50個長度單位。然後他又想把這些木棒恢復到為裁截前的狀態,但忘記了棍子的初始長度。請你設計乙個程式,幫助喬治計算棍子的可能最小長度。每一節木棒的長度都用大於零的整數表示 輸入資料 由多個案例組成,每...

POJ 1011 經典搜尋

這道題 是 比較經典的 搜尋題。題意 給出一堆小木棍的長度,需要把它們拼成幾根相同的大棍子,求 這些大棍子的最短長度 分析 這道題主要使用,深度搜尋 遞迴,當然這裡用到多次剪枝,這對於減小時間複雜度很有效。include includeusing namespace std int stick 64...

POJ 1011 搜尋剪枝

題意 給一堆木棒,這些木棒是由幾根長度相同的長木棒厥斷而成的,求最短的長木棒長度能厥成這些短的木棒。題解 所求長度肯定介於最長木棒和木棒之和中間,並且可以整除木棒之和。於是窮舉所有可能的值,選中乙個值之後,用dfs給木棒尋找組合,能找到就輸出。直接dfs會超時,所以需要剪枝。可以先排序,這樣相同的木...