NC50243 小木棍
题目
题目描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入描述
第一行为一个单独的整数N表示砍过以后的小木棍的总数。第二行为N个用空格隔开的正整数,表示N根小木棍的长度。
输出描述
输出仅一行,表示要求的原始木棍的最小可能长度。
示例1
输入
9 5 2 1 5 2 1 5 2 1
输出
6
备注
题解
知识点:DFS。
首先要枚举一个原长,再去dfs可行性,但这题关键在于剪枝。
优化:
- 原长要整除长度和
- 木棍从大到小排序,方便快速剪枝
- 访问过的木棍不再访问
- 拿取后长度超额的木棍不搜索
- 每次拼凑一根原棍从上一次访问的木棍之后开始,因为之前的都已经不可行了
- 一次失败后,后面全部相同长度的不要搜索
- 第一根或者最后一根失败代表上一根也失败直接跳出循环
以上优化缺一不可。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; int n, a[67]; int len; bool vis[67]; bool dfs(int step = 0, int sum = 0, int pos = 0) { if (sum == len) { if (step == n) return true; else sum = 0, pos = 0; } for (int i = pos;i < n;i++) { if (vis[i] || sum + a[i] > len || i > 0 && a[i - 1] == a[i] && !vis[i - 1]) continue; vis[i] = 1; if (dfs(step + 1, sum + a[i], i + 1)) return true; vis[i] = 0; if (!sum || sum + a[i] == len) break; } return false; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin >> n; int sum = 0; for (int i = 0;i < n;i++) cin >> a[i], sum += a[i]; sort(a, a + n, [&](int a, int b) {return a > b;}); for (len = a[0];len <= sum;len++) { if (sum % len) continue; if (dfs()) { cout << len << '\n'; break; } } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16482993.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效