[AcWing 167] 木棒
DFS 剪枝
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int n;
int w[N];
int sum, len;
bool st[N];
bool dfs(int u, int s, int start)
{
if (u * len == sum)
return true;
if (s == len)
return dfs(u + 1, 0, 0);
// 排除等效冗余 按照组合数枚举
for (int i = start; i < n; i ++) {
// 可行性剪枝
if (st[i] || s + w[i] > len)
continue;
st[i] = true;
if (dfs(u, s + w[i], i + 1))
return true;
st[i] = false;
// 排除等效冗余 放到头尾失败则失败
if (!s || s + w[i] == len)
return false;
// 排除等效冗余 排除掉相同值的元素
int j = i;
while (j < n && w[j] == w[i])
j ++;
i = j - 1;
}
return false;
}
void solve()
{
while (cin >> n, n) {
memset(st, false, sizeof st);
sum = 0;
for (int i = 0; i < n; i ++) {
cin >> w[i];
sum += w[i];
}
// 优化搜索顺序 从大到小排序
sort(w, w + n, greater<int>());
len = 1;
while (true) {
// 可行性剪枝
if (sum % len == 0 && dfs(0, 0, 0)) {
cout << len << endl;
break;
}
len ++;
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}
- 优化搜索顺序
从大到小排序,减少分支的数量 - 可行性剪枝
只有当单个木棒的长度 可以整除总长度 时,才进行 - 排除等效冗余
① 按照组合数枚举
② 如果当前木棍加到当前棒中失败,则直接略过后面所有长度等于当前木棍的木棍
③ 如果当前木棍在当前棒的头部失败,则一定失败
证明:假设存在一种方案,将当前木棍放到后续的棒中成功,则通过调整法,先将木棍调整到该木棍所在棒的最前面,再交换两木棒的位置,这样就把木棒调整到如果这句话的位置,出现矛盾
④ 如果当前木棍在当前棒的尾部失败,则一定失败
证明:假设存在一种方案,将当前木棍放到后续的棒中成功,由于木棒的长度都相同,那么即使不把当前木棍拼接到当前木棒,最后当前木棒拼接的长度总和还是等于当前木棍,那么通过把这一段的木棍和当前木棍调整,就会出现矛盾
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效