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. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
随机推荐
- Java_Habse_add
import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hb ...
- 喵星之旅-狂奔的兔子-docker安装和基本使用
一.前提条件 目前,CentOS 仅发行版本中的内核支持 Docker. 位.系统内核版本为 3.10 以上. 位系统.参考喵星之旅-狂奔的兔子-linux安装 二.CentOS 7下安装 Doc ...
- php从接口获取数据转成可以用的数组或其他(含转换编码)
程序开发,时常会用到将接口的json数据转换成程序可以用的,因为今天看到一个比较好的程序,贴上来,以备随时查看: /** * 将对象转成数组,并按要求转换编码 * * @param array $ar ...
- [踩坑记录] windows10 应用商店打不开 代码: 0x80131500
在某博客看到的方法,供参考,可以尝试一下,我的也是这么解决的1.打开“运行”输入 inetcpl.cpl (“WINDOWS”+“R”键,输入 inetcpl.cpl亦可)2.点开高级往下拉,勾上&q ...
- 洛谷 P1563 玩具谜题(模拟)
嗯... 题目链接:https://www.luogu.org/problem/P1563 这道题主要问题就是弄明白顺逆时针的问题,其实可以简化成一个异或的问题:当head与x异或值为零时,即为顺时针 ...
- oracle用户表字段注释
SELECT C.TABLE_NAME,NUM_ROWS,(select COMMENTS from user_tab_comments WHERE TABLE_NAME=C.TABLE_NAME) ...
- Linux - 查看所有服务状态
ubuntu: service --status-all 例如可查看ssh, apache2等服务是否开启
- 《Web安全攻防 渗透测试实战指南 》 学习笔记 (三)
Web安全攻防 渗透测试实战指南 学习笔记 (三) burp suite详解 是一款集成化渗透测试工 ...
- Informatica PowerCenter 常用转换组件一览表
原文地址:https://blog.csdn.net/yongjian1092/article/details/52176018 转换类型: 积极转换(Active):可以更改通过它来传递的数据行数, ...
- APDL获取节点和单元的结果
目录 1. 获取节点结果 1.1 获取节点应力结果 1.2 获取节点位移结果 1.3 获取节点应变结果--总应变 1.4 获取节点应变结果--弹性应变 1.5 获取节点应变结果--塑性应变 1.6 获 ...