P1120/UVA307 小木棍(sticks) 题解
题目描述
题解
注意的问题是,各个原始木棒的长度都是一样的!
说一下本题的总思路即:DFS+超强力剪枝!(详见本人的 AC 程序)
首先,我们要从小到大枚举原始木棒的长度len,也就是枚举答案,最先找到的就是最小长度。那怎么确定枚举的是正确的呢?我们用的是搜索。
如果只搜索是极不理智的,而如果有了剪枝,一切就好说了,本题的剪枝主要有五个,我们会边看程序边了解一下。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int len,n;
bool v[];
int a[];
int cnt,sum,val;
//stick 即正在拼第stick根木棒(确保前面的都拼好了)
//第stick根木棒的当前长度为cab
//拼第stick根木棒的上一根小木棒为last(有些小朋友可能会有疑问,为什么第一次搜索是dfs(1,0,1)而不是dfs(1,0,0)首先,如果dfs(1,0,0)也能过并且更正确一些,而即使dfs(1,0,1)在bfs中的第三个if中,因为v[i]==1也不会进入)
bool dfs(int stick,int cab,int last)
{
if(stick>cnt)
return true;//所有的木棒都已经拼好
if(cab==len)
return dfs(stick+,,); //当前的一根已经拼好,开始下一根
int fail=;//第二个剪枝开始了:对于每根木棒,fail记录的是最近一次尝试拼接的木棍长度。这样再回溯时就不会再尝试相同长度的木棍。
for(int i=last;i<=n;i++)//第三个剪枝开始了:限制先后加入一根原始木棍的长度是递减的。因为先拼上一个长为x的木棍再拼上一个长为y的木棍,等效于先拼上一个长为y的木棍再拼上一个长为x的木棍。所以只需要搜索其中一种即可。
{
if(v[i]==&&a[i]+cab<=len&&fail!=a[i])
{
v[i]=;
if(dfs(stick,cab+a[i],i))
return true;
v[i]=;//还原搜索前的状态。
fail=a[i];
if(cab==||cab+a[i]==len)
return false;//第四个剪枝开始了:如果在一根原始木棒中尝试拼接的第一根木棍的递归分支就以失败返回,直接判断当前分支无解。与此同时,第五个剪枝开始了,如果两个木棍的长度和与一个木棍的一样,只尝试一个的就行了(因为前两个可能会有更大的效用)
}
}
return false;//所有分支都尝试过,搜索失败。
}
int main()
{
while(cin>>n&&n)
{
sum=;
val=;
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];//为啥要累加尼?为了求原始木棒的根数,即sum/len(len是枚举的答案)
val=max(val,a[i]);
}
sort(a+,a+n+);//第一个剪枝开始了:此为优化搜索顺序,优先尝试较长的木棍
reverse(a+,a+n+);//sort从小到大排序,而reverse会将整个数组翻转(懒人做法),这样就可以达到从大到小排的结果
for(len=val;len<=sum;len++)
{
if(sum%len)
continue;
cnt=sum/len;
memset(v,,sizeof(v));
if(dfs(,,))//(1,0,1具体是啥,看上方的dfs)
{
cout<<len<<endl;
break;//确定枚举正确的第一次即为答案,立即结束
}
}
}
return ;
}
P1120/UVA307 小木棍(sticks) 题解的更多相关文章
- [UVA307]小木棍 Sticks
题目大意:有一堆小木棍,把它们接成相同长度的小木棍,问结果的小木棍的最小长度是多少,多组数据 题解:$dfs$,各种剪枝. 卡点:无 C++ Code: #include <cstdio> ...
- 【洛谷UVA307】小木棍Sticks
小木棍Sticks[传送门] 算法的话:dfs+超强剪枝: (另外注意UVA上好像不接受万能头[因为万能头WA了两次,瑟瑟发抖]) 思路: 最直接的思路,枚举木棍长度来dfs,但这样很容易就TLE了. ...
- 题解 P1120 【小木棍 [数据加强版]】
题面 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编程帮 ...
- 【Luogu P1120】小木棍
题目: 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过$50$.现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度.给出每段小木棍的长度,编程 ...
- 【题解】洛谷P1120 小木棍(搜索+剪枝+卡常)
洛谷P1120:https://www.luogu.org/problemnew/show/P1120 思路 明显是搜索题嘛 但是这数据增强不是一星半点呐 我们需要N多的剪枝 PS:需要先删去超出50 ...
- 题解0007:小木棍(P1120)
(错误记录) 题目链接:https://www.luogu.com.cn/problem/P1120 题目描述:几根同样长的木棍,小冥把它们随意砍成了n段: 然后他又吃饱了撑的想把木棍拼上: 但是这个 ...
- 洛谷P1120 小木棍(sticks数据加强版)
题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编 ...
- 一本通&&洛谷——P1120 小木棍 [数据加强版]——题解
题目传送 一道特别毒瘤能提醒人不要忘记剪枝的题. 首先不要忘了管理员的话.忘把长度大于50的木棍过滤掉真的坑了不少人(包括我). 显然是一道DFS题 .考虑剪枝. 找找搜索要面临的维度.状态:原始木棍 ...
- 洛谷 P1120 小木棍 [数据加强版]解题报告
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
随机推荐
- 02-Spring的IOC示例程序(通过id获取对象)
*******通过IOC容器创建id对象并为属性赋值******** 整体结构: ①创建一个java工程 ②导包 ③创建log4j.properties日记配置文件 # Global logging ...
- LeetCode日常小习题
LeetCode练习题: 1.给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的,并且给定的数组总是存在众数. 示例 1: 输入 ...
- Euler Sums系列(一)
\[\Large\sum_{n=1}^{\infty} \frac{H_{n}}{2^nn^4}\] \(\Large\mathbf{Solution:}\) Let \[\mathcal{S}=\s ...
- 技术学习的网站 http://www.runoob.com/
菜鸟教程:http://www.runoob.com/ W3C:https://www.w3cschool.cn/tutorial 脚本之家:https://www.jb51.net/
- Cookie API介绍
一.Java提供的操作Cookie的API Java中的javax.servlet.http.Cookie类用于创建一个Cookie Cookie类的主要方法 No. 方法 类型 描述 Cookie( ...
- netty(五) channel
问题 channel 是如何处理发送一半中断后继续重发的 channel 具体作用是什么 概述 这一节我们将介绍 Channel 和内部接口 Unsafe .其中Unsafe 是内部接口,聚合在Cha ...
- ajax中 踩过的坑
直接上图: 以前一直对 dataType 这个参数 模棱两可,只知道一般写的是 json 正解:这个dateType 指的是 ajax 返回数据的格式.比如:你想返回一个“success& ...
- Java编译器的常量优化
/* 在给变量进行赋值的时候,如果右侧的表达式当中全都是常量,没有任何变量, 那么编译器javac将会直接将若干个常量表达式计算得到结果. short result = 5 + 8; // 等号右边全 ...
- 安装多个xcode对homebrew影响
安装多个xcode,可能会导致无法识别默认使用哪个xcode的情况,这时候执行下列语句,设置默认xcode sudo xcode-select --switch /Applications/Xcode ...
- centos7.5下安装jenkins
最近从头搭建了一套python+selenium+pytest+allure+Jenkins的环境,虽然网上挺多的,不过还是记录下来,毕竟坑还是挺多的....... 先从搭建jenkins开始把! 方 ...