點此看題面
大致題意:給你\(n\)根小木棍,請你把它們拼成若干根長度相同的木棍,問你最小可能長度。
顯然的,木棍的長度肯定是\(\sum_^n len[i]\)的乙個因數,且肯定大於\(max(len[i])\)。因此,我們只要在這個範圍內列舉答案並用\(dfs\)來驗證即可。
另外,只要找到乙個答案,我們就可以立刻結束程式了(這應該是顯然的)。
這樣不就好了嗎?
等等,乙個裸的暴搜顯然是卡不過去的(如果能過當我沒說),必須要加上大量的剪枝才可以。
這道題木棍的長度在\(50\)以內,所以顯然我們可以用桶來儲存。
我們可以從大到小來列舉每乙個長度,只要當前長度加上已經拼接好的木棍的長度不會超過當前所要驗證的長度,我們就對其進行\(dfs\)。
還有乙個小優化就是,在每一次\(dfs\)結束後,若原先並沒有已經拼接好的木棍,或者已經拼接好的木棍的長度加上當前長度恰好等於當前所要驗證的長度,我們就立刻結束列舉,因為這根木棍肯定是要選的,這兩種情況下選了肯定比不選狀態更優。
#include#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define ll long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (a==b&&(b=(a=ff)+fread(ff,1,100000,stdin),a==b)?eof:*a++)
#define pc(ch) (pp_<100000?pp[pp_++]=(ch):(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=(ch)))
#define n 65
int pp_=0;char ff[100000],*a=ff,*b=ff,pp[100000];
using namespace std;
int n,maxx=0,minn=1e9,a[n+5];
inline void read(int &x)
inline void write(int x)
inline void dfs(int x,int min,int v,int ans)//用dfs來驗證乙個答案是否可行
//如果可行,就直接輸出答案,結束程式
if(v==ans) //如果當前木棍的長度剛好為要驗證的長度,說明拼好了一根木棍,就將剩餘要拼接的木棍的根數減1,並可以重新從最大的開始列舉了
if(ans-v=minn;--i)//從上一次使用的木棍長度開始從大到小列舉木棍長度 }
}int main()
for(i=maxx;;++i)//從最長的木棍的長度開始列舉
if(!(sum%i)) dfs(sum/i,maxx,0,i);//最終答案肯定是sum的因數,用dfs來驗證
}
洛谷1120小木棍
題目描述 喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過50。現在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。給出每段小木棍的長度,程式設計幫他找出原始木棍的最小可能長度。輸入輸出格式 輸入格式 輸入檔案共有二行。第一行為乙個單獨的整數n...
洛谷 1120 小木棍 資料加強版
題目描述 喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過5050。現在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。給出每段小木棍的長度,程式設計幫他找出原始木棍的最小可能長度。輸入輸出格式 輸入格式 共二行。第一行為乙個單獨的整數n表示砍...
洛谷 1120 小木棍(資料加強版)
喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過50。現在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。給出每段小木棍的長度,程式設計幫他找出原始木棍的最小可能長度。輸入格式 輸入檔案共有二行。第一行為乙個單獨的整數n表示砍過以後的小木棍的總...