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. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
随机推荐
- 91云服务器网络带宽测试,IO测试、全国ping测试
91yun服务器测试一键包介绍 一键包主要是为了让大家快速对服务器的基本状况有一个了解.考虑到天朝的网络出口问题,所以这个一键包更加偏向网络的测试. 影响测试耗时主要是下载,整个测试如果是能跑满100 ...
- allegro 16.6 铜皮显示问题
Setup-->User Preference-->display-->opengl-->staic-shapes_fill_solid打勾.可以将栅格铜皮改为实铜, Setu ...
- Java面向对象编程 -6.4
二维数组 数组的定义格式 数组的动态初始化:初始化之后数组中的每一个元素的保存的内容为其对应数据类型的默认值 声明并初始化数组: 数据类型 数组名称 [][] = new 数据类型[行个数][列个数] ...
- 【MySQL】安装及配置
" 目录 #. 概述 1. 什么是数据(Data) 2. 什么是数据库(DataBase, 简称DB) 3. 什么是数据库管理系统(DataBase Management System) 4 ...
- C# 集合类型学习
如果你掌握了一门语言的数据结构 ,那么你离掌握这门语言 也不远了 1.列表 对于list,值得一提的是 Capacity 属性,使用默认的构造函数 ,让我们用代码来说明 var intList = n ...
- list随机生成数值
List<int> numbers = Enumerable.Range(5, 10).ToList();
- CSS3绘制不规则图形,代码收集
三角形系列(三角形.倒三角.左三角.右三角.左上三角.右上三角.左下三角.右下三角) 主要用到的是:宽度高度设置为0, border的各个边的设置(各个边的透明或不透明): .triangle-up ...
- HDU5444 Elven Postman
按要求递归建树输出~ #include<cstdio> #include<algorithm> #include<cstring> using namespace ...
- leetcode: 0204 完成的
目录 大纲:0204 完成的 notes ✅1051 高度检查器 ✅ 728 自除数 brute c解答: java switch 语句 java api: array 直接有 length 属性 , ...
- DHT协议网络爬虫磁力链接和BT种子搜索引擎
系统功能和用到的技术. 系统包括几个独立的部分: 使用 Python 的 Scrapy 框架开发的网络爬虫,用来爬取磁力链接和种子: 使用 PHP CI 框架开发的简易网站: 搜索引擎目前直接使用的 ...