【Luogu P1120】小木棍
题目:
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过$50$。
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
分析:
可以很轻易的写出$\rm dfs$的程序:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int MAXN = 105; 6 7 int st[MAXN], n, s = 0; 8 bool vis[MAXN]; 9 10 void dfs(int cur, int len, int w) { 11 if(cur == s / len) { 12 cout << len << endl; 13 exit(0); 14 } 15 if(w == 0) { 16 dfs(cur + 1, len, len); 17 return; 18 } 19 for(int i = n - 1; i >= 0; i--) 20 if(w - st[i] >= 0 && !vis[i]) { 21 vis[i] = true; 22 dfs(cur, len, w - st[i]); 23 vis[i] = false; 24 } 25 } 26 27 int main() { 28 cin >> n; 29 for(int i = 0; i < n; i++) { 30 cin >> st[i]; 31 s += st[i]; 32 } 33 sort(st, st + n); 34 for(int i = 1; i <= s; i++) 35 if(s % i == 0) { 36 dfs(0, i, i); 37 } 38 return 0; 39 }
然而,上面的代码时间复杂度是$O(n! \log \sum a_i)$左右,显然不可以接受。
首先我们发现:
$1$)从按木棍大到小搜索,因为长度小的比长度大的更加灵活。
$2$)若当前剩余长度$\lt$最小的木棍的长度,那么这个方案就没用了
$3$)如果当前长度的木棍拼接无法成功,那么同样长度的木棍拼接也无法成功。
$4$)若选择这个木棍来拼接后没有成功,且当前的剩余长度$=$这个木棍的长度,应当直接退出,因为这根木棍显然要自成一个大木棍,而拼下去却失败,说明剩下的小木棍无法拼接成这根木棍。
$5$)若选择这个木棍来拼接后没有成功,且当前的剩余长度$=$我们枚举的长度$len$,应当直接退出,因为这根木棍肯定会需要用上,而这里失败了,说明它最后用不到了。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int MAXN = 105, inf = 1e9; 6 7 int st[MAXN], n, s = 0, len, maxi = -inf, mini = inf; 8 bool vis[MAXN]; 9 10 void dfs(int cur, int w, int last) { 11 if(cur == s / len) { 12 cout << len << endl; 13 exit(0); 14 } 15 if(w == 0) { 16 dfs(cur + 1, len, -1); 17 return; 18 } 19 if(w < mini) return; 20 for(register int i = last + 1; i < n; i++) 21 if(w - st[i] >= 0 && !vis[i]) { 22 vis[i] = true; 23 dfs(cur, w - st[i], i); 24 vis[i] = false; 25 while(i && st[i] == st[i - 1]) i++; 26 if(w == st[i] || w == len) return; 27 } 28 } 29 30 int main() { 31 cin >> n; 32 for(register int i = 0; i < n; i++) { 33 cin >> st[i]; 34 s += st[i]; 35 maxi = max(maxi, st[i]); 36 mini = min(mini, st[i]); 37 } 38 sort(st, st + n, [](int x, int y){ 39 return x > y; 40 }); 41 for(register int i = maxi; i <= s; i++) 42 if(s % i == 0) { 43 len = i; 44 dfs(0, i, -1); 45 } 46 return 0; 47 }

浙公网安备 33010602011771号