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. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
随机推荐
- python 中对list去重
本文去重的前提是要保证顺序不变,本文给出了多种实现方法,需要的朋友可以参考下 1.直观方法 最简单的思路就是: ids = [1,2,3,3,4,2,3,4,5,6,1] news_ids = [] ...
- JQuery checkbox多选框组选中提交,当选择某(无)一项,其他项禁止选中
在项目中难免会遇到一些表单的提交,尤其是多选框中,当用户选择了某一项时,禁止其他项的选择.所以为了避免这样的冲突,所以我们前端就得控制一下了,下面就来个简单demo,记录一下,有需要的伙伴可以拿去耍耍 ...
- 如何利用wx.login方法获取openid和sessionKey
1, wx.login(Object object) 调用接口获取登录凭证(code).通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key) ...
- 吴裕雄 python 神经网络——TensorFlow 循环神经网络处理MNIST手写数字数据集
#加载TF并导入数据集 import tensorflow as tf from tensorflow.contrib import rnn from tensorflow.examples.tuto ...
- 重新梳理IT知识之java-05面向对象(一)
一.Java面向对象学习的三条主线: 1.Java类及类的成员:属性.方法.构造器:代码块.内部类 2.面向对象的三大特征:封装性.继承性.多态性.(抽象性) 3.其他关键字:this.super.s ...
- 解决ifarme在ios下无法使用
在第一层的config 添加 <access origin="*" /><allow-navigation href="*" />< ...
- Python socket day3
UDP聊天室 本地回环(127.0.0.1) 本地回环是每台电脑都有的,只能用于自身电脑的通讯,无论你的IP地址是多少,只要发送方输入的目的IP为127.0.0.1 ,自身便能接受得到数据 测试本地回 ...
- 【PAT甲级】1096 Consecutive Factors (20 分)
题意: 输入一个int范围内的正整数,输出它最多可以被分解为多少个连续的因子并输出这些因子以*连接. trick: 测试点5包含N本身是一个素数的数据,此时应当输出1并把N输出. 测试点5包含一个2e ...
- dateadd()日期加法运算
- django登陆界面报错InternalError at /admin/polls/question/add/
登陆界面报错信息如下: 改为输入英文,正确