题目:

乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过$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】小木棍的更多相关文章

  1. [Luogu P1120]小木棍·加强版

    #\(\mathcal{Description}\) 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过 \(50\) . 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开 ...

  2. Luogu P1120 小木棍 [数据加强版] 来来来我们一起来剪枝,剪枝,剪枝、、、

    好啊...太棒了... dfs(拼到第几根木棍,这根木棍剩余长度,上一根木棍的位置) len是木棍的长度,cnt是木棍的个数 震撼人心的剪枝: 1.枚举长度从最大的木棍开始,直到sum/2,因为之后只 ...

  3. Luogu P1120 小木棍 [数据加强版]

    看了题目心中只有一个字——搜索!!! 但是很显然,朴素的搜索(回溯)绝壁超时. 剪枝&优化(要搞很多,要不然过不了) 1:从小到大搜索它们的因数,这样找到就exit. 2:将数据从大到小排序, ...

  4. 洛谷 P1120 小木棍 [数据加强版]解题报告

    P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...

  5. 洛谷——P1120 小木棍 [数据加强版]

    P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍 ...

  6. 洛谷 P1120 小木棍 [数据加强版]

    P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...

  7. 洛谷P1120 小木棍 [数据加强版](搜索)

    洛谷P1120 小木棍 [数据加强版] 搜索+剪枝 [剪枝操作]:若某组拼接不成立,且此时 已拼接的长度为0 或 当前已拼接的长度与刚才枚举的长度之和为最终枚举的答案时,则可直接跳出循环.因为此时继续 ...

  8. 【题解】洛谷P1120 小木棍(搜索+剪枝+卡常)

    洛谷P1120:https://www.luogu.org/problemnew/show/P1120 思路 明显是搜索题嘛 但是这数据增强不是一星半点呐 我们需要N多的剪枝 PS:需要先删去超出50 ...

  9. 洛谷P1120 小木棍 [搜索]

    题目传送门 题目描述乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍 ...

  10. 洛谷 P1120 小木棍 dfs+剪枝

    Problem Description [题目链接] https://www.luogu.com.cn/problem/P1120 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不 ...

随机推荐

  1. 六、C++离散傅里叶逆变换

    C++离散傅里叶逆变换 一.序言: 该教程承接上文的离散傅里叶变换,用于进行离散傅里叶逆变换. 二.设计目标 对复数数组进行离散傅里叶逆变换,并生成可供使用的图像类. 三.详细步骤 输入:经傅里叶变换 ...

  2. Excel2Dataset

    //获取用户打开的Excel文档路径 private stringkkk() { OpenFileDialog selectFile = new OpenFileDialog(); selectFil ...

  3. git图形管理工具

    在windows下使用git命令行工具对非开发人员还是挺困难的,还好有TortoiseGit这个工具svn客户端用TortoiseSVNgit客户端用TortoiseGit 网址:https://to ...

  4. Python开发第二篇

    运算符 1.算术运算符 % 取余运算符,返回余数 ** 幂运算符 //返回商的整数部分 2.逻辑运算符 and  与运算符 a and b 如果a为False是,表达式为False,如果a为True返 ...

  5. innobackupex 全备、增备脚本

    全备脚本:innobackupex --defaults-file=/etc/my.cnf --user root --password mypasswd /mydata/fullbak/ 增备脚本: ...

  6. 利用Python实现 队列的算法

    以下内容都是来自“悟空“大神的讲解,听他的视频课,利用Python实现堆栈的算法,自己做了一些小总结,可能会存在自己理解的一些误区, 1.栈的实现 队列的特征是先进先出,同我们生活中的队列具有相同的特 ...

  7. 【BZOJ2730】[HNOI2012] 矿场搭建(找割点)

    点此看题面 大致题意: 一张无向图,要求你在去掉任意一个节点之后,剩余的每个节点都能到达一个救援出口,问至少需要几个救援出口. 第一步:\(Tarjan\)求割点 首先,我们要跑一遍\(Tarjan\ ...

  8. Beyond Compare在Mac下永久试用

    转自 作者:忆如初 链接:https://www.jianshu.com/p/596b4463eacd 来源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处. 亲测可用 一. ...

  9. daemon函数实现原理 守护进程

    linux提供了daemon函数用于创建守护进程,实现原理如下: #include <unistd.h> int daemon(int nochdir, int noclose); 1.  ...

  10. GreenPlum查看表和数据库大小

    表大小 zwcdb=# select pg_size_pretty(pg_relation_size('gp_test')); pg_size_pretty ---------------- 1761 ...