1.考慮到長木棍的可能長度在最長小木棍長度與所有小木棍總長度之間,先打乙個暴力搜尋,在這個範圍內dfs找答案,顯然會tle,估計有21分左右。
2.長木棍的數目為整數,所以長木棍的長度為總長度的約數。
3.如果當前處理的木棍長度加上最短的小木棒長度都超過了搜尋的答案,顯然不存在,剪枝。
4.如果剩餘總長度加上當前處理的木棍長度都達不到目標長度,剪枝。
5.更短的木棒比長木棒更加靈活,所以對小木棒長度進行排序後從大到小列舉。
6.因為木棒在排序後有序,所以每次處理的木棒一定在上一根處理的木棒之後,傳遞上一根木棒的位置。
*7.(重要剪枝)某次操作中如果已經完成了一根完整的長木棍,而在更深層次的dfs中又得出答案錯誤,則當前迴圈可以直接跳出,因為對後續更短的木棒進行操作會有重複計算,剪枝。
code:
#include #include #include #include #include #include #include using namespace std;
//mystery_sky
//#define m 1000100
#define inf 0x3f3f3f3f
#define ll long long
inline int read()
while(c >= '0' && c <= '9')
return x * f;
}int n, tot, l, r;
int a[m];//每根小木棍的長度。
bool flag = false, vis[m];
int minn = inf;
inline bool check_1(int sum, int goal)
void dfs(int depth, int sum, int num, int goal, int rest, int pre)//已取了多少小木棒,當前在拼的小木棒總長,已經拼好了多少該長度的小木棒,目標長度,總共還剩多長,上一段在哪。
if(check_1(sum, goal)) return;//剪枝1 -> 21分
if(rest + sum < goal) return;//剪枝5 -> 39分
for(int i = 1; i <= tot; i++)
} for(int i = pre; i >= 1; i--)
else if(sum + a[i] == goal)
if(sum + a[i] == goal || sum == 0) break;//*重要剪枝:57分以外的53分。
while(a[i] == a[i-1]) i--;
} }}int main()
} if(s)
sort(a+1, a+1+tot);
for(int i = l; i <= r; i++)
} }return 0;
}
剪枝真快樂 P1120 小木棍 資料加強版
喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過 50 現在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。給出每段小木棍的長度,程式設計幫他找出原始木棍的最小可能長度。首先在讀入的時候忽略掉長度大於50的木棍 最重要 順便還要記錄一下最短的木...
P1120 小木棍 資料加強版
原題鏈結 不得不說,這題真的是一道深度搜尋毒瘤題qwq,整整坑了我乙個上午。先說一下大體思路 1.讀入資料的同時 注意過濾掉長度大於50的木棍 算出所有小木棍的總和sum,因為至少所有的小木棍會拼成一根長度為sum的超大木棍 2.找出所有小木棍中長度最大的那根max,原始長度len一定大於等於這個m...
P1120 小木棍 資料加強版
一道不錯的剪枝題,用到的剪枝優化比較多,剪枝思路也值得學習 在這裡我只採取了能通過此題的剪枝,似乎還可以繼續優化?剪枝講解在注釋裡 include include include include includeusing namespace std const int maxn 70 inline ...