Sticks(UVA - 307)【DFS+剪枝】
Sticks(UVA - 307)
算法
DFS+剪枝
1.这道题题意就是说原本有一些等长的木棍,后来把它们切割,切割成一个个最长为50单位长度的小木棍,现在想让你把它们组合成一个个等长的大木棍,要求这个拼接成的大木棍的长度最小。问最小长度是多少。(注意,在接下来的介绍中,将最后的大木棍表述为拼接木棍,小木棍还是叫小木棍)
2.看完这个题,基本思路是从一个小木棍开始找,找到一个未使用的小木棍后拼接,当拼接成的长度是所有小木棍长度和的约数时,就暂时把它定义为拼接木棍的最小长度,然后计算最后需拼接成多少个这个长度的拼接木棍,然后继续寻找,达到这个长度后累加,如果实在没有,重新定义拼接木棍的最下长度。
如果按部就班的按照上面的基本思路做肯定会超时的,而且涉及的点比较多,因为当你所找到的那个最小长度不能够让所有小木棍都能拼接成时,还需继续寻找,这样过于复杂。
那么换个思路,既然是拼接木棍,那么最终拼接木棍的最小长度一定大于等于所有小木棍的最大长度。
那么我们就可以从小木棍的最大长度这个地方开始枚举拼接木棍的长度,这是其中一个可以优化的地方。那什么时候到头呢,拼接木棍的长度最大可以枚举到所有小木棍的长度和,然后就不能再大了。考虑到拼接木棍的长度是小木棍长度和的约数,那么就可以枚举到长度和/2,因为大于长度和/2的部分就没有长度和的约数了(除了长度和本身),这样可以节省一定的时间。当满足条件时,直接退出循环,输出即可,如果循环了所有约数都不满足,直接输出长度和即可。
下面介绍几个剪枝的地方:
- 将存储小木棍长度的数组从大到小排序,这样做的原因是长度大的小木棍相对于长度小的小木棍一定有相对较小的选择,这样在一定情况下节省了时间。
- 枚举拼接木棍的长度时,只考虑约数(小木棍长度和的约数),其余的无需考虑。
- 如果当前木棍与前一个木棍长度相同,并且前一个木棍拼接失败,那么直接跳过当前木棍即可。
- 当目前拼接长度为0时,但尝试了所有的木棍都没有拼接成功,则证明这个拼接木棍的长度无法拼成,return false即可。
3.这道题是一道典型的DFS剪枝题目,涉及的剪枝比较多,稍有一点没涉及到就会TLE。
C++ 代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1000;
int n, units[N];
int sum_length; /*所有小木棍的总长度*/
bool st[N]; /*标记当前小木棍是否被使用*/
int res; /*拼接长度*/
int cnt; /*在拼接长度为res时最终能形成的拼接木棍的个数*/
bool dfs(int len, int k, int i) /*len表示当前的拼接长度,k表示满足res的拼接木棍的个数,i表示下标为i的这个木棍已经考虑完,再枚举时从下一个木棍开始枚举即可*/
{
if(len == res)
{
k++; /*达到拼接长度时,累加拼接木棍的个数*/
len = i = 0;
}
if(k == cnt) return true;
for(int j = i + 1; j < n; j++)
{
if(st[j]) continue; /*当前木棍已经被使用,则不能再使用*/
if(units[j] == units[j-1] && !st[j-1]) continue; /*前一个木棍与它长度相同,但没被使用,那该木棍也无需再验证是否需要使用了*/
if(units[j] + len > res) continue; /*大于拼接长度,则不能考虑*/
st[j] = true;
if(dfs(len + units[j], k, j))
return true;
st[j] = false;
if(len == 0)
return false;
}
return false;
}
int main()
{
while(cin >> n && n)
{
sum_length = 0;
for(int i = 0; i < n; i++)
{
cin >> units[i];
sum_length += units[i];
}
sort(units, units + n, greater<int>());
for(res = units[0]; res <= sum_length / 2; res ++)
{
memset(st, 0, sizeof st);
if(sum_length % res != 0) continue;
cnt = sum_length / res; /*预测的初始木棒个数*/
st[0] = true; /*标记第一个最长的小木棍被使用*/
if(dfs(units[0], 0, 0))
{
cout << res << endl;
break;
}
}
if(res > sum_length / 2) /*大于它时,说明没有可形成的长度,直接输出长度和即可*/
cout << sum_length << endl;
}
}
Sticks(UVA - 307)【DFS+剪枝】的更多相关文章
- DFS(剪枝) POJ 1011 Sticks
题目传送门 /* 题意:若干小木棍,是由多条相同长度的长木棍分割而成,问最小的原来长木棍的长度: DFS剪枝:剪枝搜索的好题!TLE好几次,终于剪枝完全! 剪枝主要在4和5:4 相同长度的木棍不再搜索 ...
- poj 1011 Sticks (DFS+剪枝)
Sticks Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 127771 Accepted: 29926 Descrip ...
- poj 1011 :Sticks (dfs+剪枝)
题意:给出n根小棒的长度stick[i],已知这n根小棒原本由若干根长度相同的长木棒(原棒)分解而来.求出原棒的最小可能长度. 思路:dfs+剪枝.蛮经典的题目,重点在于dfs剪枝的设计.先说先具体的 ...
- *HDU1455 DFS剪枝
Sticks Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
- hdu1455 dfs+剪枝
Sticks Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
- POJ 3009 DFS+剪枝
POJ3009 DFS+剪枝 原题: Curling 2.0 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16280 Acce ...
- poj 1724:ROADS(DFS + 剪枝)
ROADS Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10777 Accepted: 3961 Descriptio ...
- DFS+剪枝 HDOJ 5323 Solve this interesting problem
题目传送门 /* 题意:告诉一个区间[L,R],问根节点的n是多少 DFS+剪枝:父亲节点有四种情况:[l, r + len],[l, r + len - 1],[l - len, r],[l - l ...
- HDU 5952 Counting Cliques 【DFS+剪枝】 (2016ACM/ICPC亚洲区沈阳站)
Counting Cliques Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
随机推荐
- Cubmap
视差 Cubmap https://chengkehan.github.io/LocalCubmap.html http://www.manew.com/thread-93923-1-1.html h ...
- 实操ES6之Promise
箭头函数和this 写Promise的时候,自然而然会使用箭头函数的编写方式.箭头函数就是.Neter们熟知的lambda函数,已经被大部分主流语言支持,也受到了广大码农的交口称赞,但是Jser们却会 ...
- iptables实用知识 ,一文学会配置linux防火墙
目录 1.防火墙的概念 2. linux防火墙 3.linux数据包处理流程 3.1 linux 防火墙将以上流程,固定区分为5个流程节点 3.2 数据流程 4 linux防火墙的实现机制 4.1 i ...
- Activiti7 学习总结
什么是工作流? 就是通过计算机对业务流程进行自动化处理,实现多个参与者按照预定义的流程去自动执行业务流程 什么是Activiti? Activiti是一个工作流引擎,开源的架构,基于BPMN2.0标准 ...
- centOS7 设置mysql数据库外网可以访问
1.查看目前防火墙是否对外开发了3306端口 firewall-cmd --list-all 2.查看3306端口是否开放 firewall-cmd --query-port=3306/tcp no ...
- python3 venv
介绍 venv 是什么? python3 自带的虚拟环境 为什么需要虚拟环境? 当服务器中需要搭建共存多个环境时(不同环境之间会有冲突) 比如说环境1:需要mongo:3.6版本 / 但是环境2:需要 ...
- Mybatis----Mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "- ...
- CSS居中的多种方法
1.水平居中:text-align 与 inline-block 的配合 <div id = "div_center_align"> <div id = &quo ...
- HTTP 协议类
HTTP 协议的主要特点 简单快速:每个资源的URL是固定的 灵活:在每个 http 协议中都有一个头部分有一个数据类型,通过一个 http 协议就可以完成不同数据类型的传输 无连接:连接一次就好断掉 ...
- C#类库推荐 拼多多.Net SDK,开源免费!
背景介绍 近两年拼多多的发展非常迅速,即便口碑一般,也没有网页端,奈何我们已经全面小康,6亿月收入1000以下,9亿月收入2000以下,所以因为价格原因使用拼多多的用户也越来越多了.同样的,拼多多也开 ...