不是題解!不是題解!不是題解!重要的事情說三遍!純屬個人學習筆記!
傳送門:p1120
ac**:
#include
using namespace std;
int s[
100]
,vis[
100]
,next1[
100]
;bool ok;
int number,len;
int sum;
inline
intread()
while
(ch>=
'0'&&ch<=
'9')
return f*w;
} bool cmp
(int a,
int b)
void
dfs(
int k,
int last,
int rest)
for( i=
1;i<=sum;i++
) vis[i]=1
;dfs
(k+1
,i,len-s[i]);
vis[i]=0
;if(ok)
return;}
int l=last+
1,r=sum,mid;
while
(l//cout(int i=l;i<=sum;i++)}
}int
main()
sort
(s+1
,s+1
+sum,cmp)
; next1[sum]
=sum;
for(
int i=sum-
1;i;i--
)for
(len=s[1]
;len<=ans/
2;len++)}
cout
}
寫搜尋對於我來說是一件很痛苦的事情,因為都知道這是搜尋,但如果剪枝(優化)剪不好就是無限被t。並且這類搜尋題如果出現一些神仙優化,剪枝就是腦子**。
所以這裡就拿這道題來聊聊思路。
1.如果直接暴力搜尋該怎麼寫?
不難分析出原始木塊的長度一定處於max(s[i])
到sum
之間,所以我們可以用原始長度為操作點,分析每一種長度是否滿足情況,如果出現滿足條件的長度,就直接輸出,因為可以保證輸出的是最小值。
確定了原始長度len
之後,就要分析,哪些木棍組合可以組合成原始長度為len
的木棍 。
這裡最暴力可以想到搜尋,找出所有可能的情況,並且分析是否可滿足初始條件。
2,確定了最暴力的解法之後,優化成了最大boss。
出現的木棍長度可能有重複,如果已知len (i)
不滿足條件,下一次搜尋的應該是與len(i)
不同的數,所以可以建立乙個next陣列,避免重複。
next陣列的建立也很有意思,在上次模擬賽中有乙個簽到題就要用到next陣列進行優化,但那時候我還不會,就卡了很久。
這裡給出的**可以當成板子來記:
for
(int i=sum-
1;i;i--
)
在遍歷搜尋的時候,不難想到,每次搜尋都要搜尋比現在位置後的數,不用搜尋比現在位置還前的數字,因為如果下乙個數字出現在當前位置之前就一定在之前的搜尋中查詢過。所以每次向後找就行了,
在找下乙個木棍的時候,利用二分的方法可以快速查詢到可行的位置,如果不用二分會被t掉乙個點。
本題最神仙的是if(rest==s[i]||rest==len)return ;
這個點我絕對想不到。
P1120 小木棍 資料加強版 (搜尋 剪枝)
原題 題意 有n 65 根小木棍,長度a ia i ai 50 這些小木棍是由x根l長木棍切割而得,現在x和l不確定,讓你求最小的l。題目說了如果出現大於50的木棍要忽略。解析 首先當然是要列舉長度l了,下界為給出長度最大值mama ma,上界為所有木棍長度和sum sumsu m。當然sum su...
P1120 小木棍 資料加強版 (搜尋剪枝)
include using namespace std const int maxn 70 const int maxv 3260 int it num 0 int s,n,l maxn bool vis maxn s maxn maxv bool cmp int lhs,int rhs bool ...
搜尋 P1120 小木棍
喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過5050。現在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。給出每段小木棍的長度,程式設計幫他找出原始木棍的最小可能長度。共二行。第一行為乙個單獨的整數n表示砍過以後的小木棍的總數,其中n 65...