【Luogu P1120】小木棍
题目:
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过$50$。
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
分析:
可以很轻易的写出$\rm dfs$的程序:
#include <bits/stdc++.h> using namespace std; const int MAXN = ; int st[MAXN], n, s = ;
bool vis[MAXN]; void dfs(int cur, int len, int w) {
if(cur == s / len) {
cout << len << endl;
exit();
}
if(w == ) {
dfs(cur + , len, len);
return;
}
for(int i = n - ; i >= ; i--)
if(w - st[i] >= && !vis[i]) {
vis[i] = true;
dfs(cur, len, w - st[i]);
vis[i] = false;
}
} int main() {
cin >> n;
for(int i = ; i < n; i++) {
cin >> st[i];
s += st[i];
}
sort(st, st + n);
for(int i = ; i <= s; i++)
if(s % i == ) {
dfs(, i, i);
}
return ;
}
然而,上面的代码时间复杂度是$O(n! \log \sum a_i)$左右,显然不可以接受。
首先我们发现:
$1$)从按木棍大到小搜索,因为长度小的比长度大的更加灵活。
$2$)若当前剩余长度$\lt$最小的木棍的长度,那么这个方案就没用了
$3$)如果当前长度的木棍拼接无法成功,那么同样长度的木棍拼接也无法成功。
$4$)若选择这个木棍来拼接后没有成功,且当前的剩余长度$=$这个木棍的长度,应当直接退出,因为这根木棍显然要自成一个大木棍,而拼下去却失败,说明剩下的小木棍无法拼接成这根木棍。
$5$)若选择这个木棍来拼接后没有成功,且当前的剩余长度$=$我们枚举的长度$len$,应当直接退出,因为这根木棍肯定会需要用上,而这里失败了,说明它最后用不到了。
#include <bits/stdc++.h> using namespace std; const int MAXN = , inf = 1e9; int st[MAXN], n, s = , len, maxi = -inf, mini = inf;
bool vis[MAXN]; void dfs(int cur, int w, int last) {
if(cur == s / len) {
cout << len << endl;
exit();
}
if(w == ) {
dfs(cur + , len, -);
return;
}
if(w < mini) return;
for(register int i = last + ; i < n; i++)
if(w - st[i] >= && !vis[i]) {
vis[i] = true;
dfs(cur, w - st[i], i);
vis[i] = false;
while(i && st[i] == st[i - ]) i++;
if(w == st[i] || w == len) return;
}
} int main() {
cin >> n;
for(register int i = ; i < n; i++) {
cin >> st[i];
s += st[i];
maxi = max(maxi, st[i]);
mini = min(mini, st[i]);
}
sort(st, st + n, [](int x, int y){
return x > y;
});
for(register int i = maxi; i <= s; i++)
if(s % i == ) {
len = i;
dfs(, i, -);
}
return ;
}
【Luogu P1120】小木棍的更多相关文章
- [Luogu P1120]小木棍·加强版
#\(\mathcal{Description}\) 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过 \(50\) . 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开 ...
- Luogu P1120 小木棍 [数据加强版] 来来来我们一起来剪枝,剪枝,剪枝、、、
好啊...太棒了... dfs(拼到第几根木棍,这根木棍剩余长度,上一根木棍的位置) len是木棍的长度,cnt是木棍的个数 震撼人心的剪枝: 1.枚举长度从最大的木棍开始,直到sum/2,因为之后只 ...
- Luogu P1120 小木棍 [数据加强版]
看了题目心中只有一个字——搜索!!! 但是很显然,朴素的搜索(回溯)绝壁超时. 剪枝&优化(要搞很多,要不然过不了) 1:从小到大搜索它们的因数,这样找到就exit. 2:将数据从大到小排序, ...
- 洛谷 P1120 小木棍 [数据加强版]解题报告
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
- 洛谷——P1120 小木棍 [数据加强版]
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍 ...
- 洛谷 P1120 小木棍 [数据加强版]
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
- 洛谷P1120 小木棍 [数据加强版](搜索)
洛谷P1120 小木棍 [数据加强版] 搜索+剪枝 [剪枝操作]:若某组拼接不成立,且此时 已拼接的长度为0 或 当前已拼接的长度与刚才枚举的长度之和为最终枚举的答案时,则可直接跳出循环.因为此时继续 ...
- 【题解】洛谷P1120 小木棍(搜索+剪枝+卡常)
洛谷P1120:https://www.luogu.org/problemnew/show/P1120 思路 明显是搜索题嘛 但是这数据增强不是一星半点呐 我们需要N多的剪枝 PS:需要先删去超出50 ...
- 洛谷P1120 小木棍 [搜索]
题目传送门 题目描述乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍 ...
- 洛谷 P1120 小木棍 dfs+剪枝
Problem Description [题目链接] https://www.luogu.com.cn/problem/P1120 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不 ...
随机推荐
- 六、C++离散傅里叶逆变换
C++离散傅里叶逆变换 一.序言: 该教程承接上文的离散傅里叶变换,用于进行离散傅里叶逆变换. 二.设计目标 对复数数组进行离散傅里叶逆变换,并生成可供使用的图像类. 三.详细步骤 输入:经傅里叶变换 ...
- Excel2Dataset
//获取用户打开的Excel文档路径 private stringkkk() { OpenFileDialog selectFile = new OpenFileDialog(); selectFil ...
- git图形管理工具
在windows下使用git命令行工具对非开发人员还是挺困难的,还好有TortoiseGit这个工具svn客户端用TortoiseSVNgit客户端用TortoiseGit 网址:https://to ...
- Python开发第二篇
运算符 1.算术运算符 % 取余运算符,返回余数 ** 幂运算符 //返回商的整数部分 2.逻辑运算符 and 与运算符 a and b 如果a为False是,表达式为False,如果a为True返 ...
- innobackupex 全备、增备脚本
全备脚本:innobackupex --defaults-file=/etc/my.cnf --user root --password mypasswd /mydata/fullbak/ 增备脚本: ...
- 利用Python实现 队列的算法
以下内容都是来自“悟空“大神的讲解,听他的视频课,利用Python实现堆栈的算法,自己做了一些小总结,可能会存在自己理解的一些误区, 1.栈的实现 队列的特征是先进先出,同我们生活中的队列具有相同的特 ...
- 【BZOJ2730】[HNOI2012] 矿场搭建(找割点)
点此看题面 大致题意: 一张无向图,要求你在去掉任意一个节点之后,剩余的每个节点都能到达一个救援出口,问至少需要几个救援出口. 第一步:\(Tarjan\)求割点 首先,我们要跑一遍\(Tarjan\ ...
- Beyond Compare在Mac下永久试用
转自 作者:忆如初 链接:https://www.jianshu.com/p/596b4463eacd 来源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. 亲测可用 一. ...
- daemon函数实现原理 守护进程
linux提供了daemon函数用于创建守护进程,实现原理如下: #include <unistd.h> int daemon(int nochdir, int noclose); 1. ...
- GreenPlum查看表和数据库大小
表大小 zwcdb=# select pg_size_pretty(pg_relation_size('gp_test')); pg_size_pretty ---------------- 1761 ...