[暑假集训Day3T1]小木棍
经典搜索题。
考虑以下9种优化
1)按木棍长度排序,使得较大长度的木棍被较早的选出。
2)只找能够整除的木棍长度,因为不能被sum整除一定不会出整数根,自然也就不是最优解。
3)枚举木棍长度时只需从最大的木棍长度(拼出的木棍长度不会小于最大的长度也不会大于总长度)枚举至总和的二分之一。如果还没有出解那么答案一定是总和(sum/2~sum-1之间一定没有解)。
4)打的标记可以在回溯去除,不用每次memset,常数会低一点,算是一个小优化~
5)在拼的木棍根数达到所需要的ans值时,打上标记及时退出,在其他进行了dfs的地方回溯时也要及时退出。
6)在需要拼新的一根木棍时,选一个未被使用的木棍中最大的进行搜索
7)只找木棍长度不大于上一次搜索木棍长度的木棍来搜索
8)当前木棍长度不能进行拼接时,同长度的木棍也肯定不能,因此可以直接跳过
9)最重要的一点!!!(我看书上写的不如这位大佬写得好,我也想不出来更好的语言来描述,以下直接引用这位大佬的题解:Author:Kaori,洛谷题解第一篇即是):
如果当前长棍剩余的未拼长度等于当前木棍的长度或原始长度,继续拼下去时却失败了,就直接回溯并改之前拼的木棍。有些人不太明白这个优化,这里简单说一下:
当前长棍剩余的未拼长度等于当前木棍的长度时,当前木棍明显只能自组一根长棍,但继续拼下去却失败,说明这根木棍不能自组?!这根木棍不自组就没法用上了,所以不用搜更短的木棍了,直接回溯,改之前的木棍;
当前长棍剩余的未拼长度等于原始长度时,说明这根原来的长棍还一点没拼,现在正在放入一根木棍。很明显,这根木棍还没有跟其它棍子拼接,如果现在拼下去能成功话,它肯定是能用上的,即自组或与其它还没用的木棍拼接。但继续拼下去却失败,说明现在这根木棍不能用上,无法完成拼接,所以直接回溯,改之前的木棍。
加入以上九种优化后,即使是指数级的DFS算法也可以较快的计算出结果,可见搜索程序中剪枝的重要性。
下面给出参考代码:
#pragma GCC optimize(3,"Ofast","inline")//吸口臭氧跑得更快~~~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,stick[],sum,ans,ready,len,minn,used[],edge;
bool cmp(int a,int b)//优化1
{
return a>b;
}
void dfs(int num,int node,int rest)
{
if(num==ans){ready=;return;}//优化5
if(rest==)
{
int po=;
for(int i=;i<=n;i++)
{
if(!used[i])
{
used[i]=;
po=i;
break;
}
}
dfs(num+,po,len-stick[po]);//优化6
used[po]=;//优化4
if(ready)return;//优化5
}
for(int i=node+;i<=n;i++)//优化7
{
if(!used[i]&&rest>=stick[i])
{
used[i]=;
dfs(num,i,rest-stick[i]);
used[i]=;
if(ready||rest==stick[i]||rest==len)return;//优化5和9
while(i<n&&stick[i+]==stick[i])i++;//优化8
if(i==n)return;
}
}
}
int main()
{
cin>>n;
for(int i=;i<=n;i++)
{
int r;
cin>>r;
if(r>)
{
i--;
n--;
continue;
}
stick[i]=r;
sum+=stick[i];
minn=max(minn,stick[i]);
}
sort(stick+,stick+n+,cmp);
for(int i=minn;i<=sum/;i++)//优化3
{
if(sum%i!=)continue;//优化2
//memset(used,0,sizeof(used));
ans=sum/i;
ready=;
len=i;
used[]=;
dfs(,,len-stick[]);
if(ready)
{
cout<<len<<endl;
return ;
}
}
cout<<sum<<endl;
return ;
}
[暑假集训Day3T1]小木棍的更多相关文章
- 2015UESTC 暑假集训总结
day1: 考微观经济学去了…… day2: 一开始就看了看一道题目最短的B题,拍了半小时交了上去wa了 感觉自己一定是自己想错了,于是去拍大家都过的A题,十分钟拍完交上去就A了 然后B题写了一发暴力 ...
- STL 入门 (17 暑假集训第一周)
快速全排列的函数 头文件<algorithm> next_permutation(a,a+n) ---------------------------------------------- ...
- 洛谷P1120小木棍[DFS]
题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编 ...
- 小木棍 (codevs 3498)题解
[问题描述] 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过100. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长 ...
- 洛谷P1120 小木棍
洛谷1120 小木棍 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长 ...
- P1120 小木棍 [数据加强版] 回溯法 终极剪枝
题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过5050. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度 ...
- 洛谷 P1120 小木棍 [数据加强版]解题报告
P1120 小木棍 [数据加强版] 题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它 ...
- 题解 P1120 【小木棍 [数据加强版]】
题面 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编程帮 ...
- [Luogu P1120]小木棍·加强版
#\(\mathcal{Description}\) 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过 \(50\) . 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开 ...
随机推荐
- 88-基于FMC接口的2路CameraLink Base输入子卡模块
基于FMC接口的2路CameraLink Base输入子卡模块 1.板卡概述 FMC连接器是一种高速多pin的互连器件,广泛应用于板卡对接的设备中,特别是在xilinx公司的所有开发板中都使用.该Ca ...
- tf.nn.top_k
评估操作对于测量神经网络的性能是有用的. 由于它们是不可微分的,所以它们通常只是被用在评估阶段 tf.nn.top_k(input, k, name=None) 这个函数的作用是返回 input 中每 ...
- shelve模块 xml模块
# import shelve# f=shelve.open('db.shl')# # f['stu1']={'name':'alex1','age':28}# # f['stu2']={'name' ...
- w = tf.Variable(<initial-value>, name=<optional-name>)
w = tf.Variable(<initial-value>, name=<optional-name>)
- centos7标准版命令界面和图形界面相互切换
1.root登陆终端 2.输入命令 vi /etc/inittab ,查看两种界面的启动模式: 3.退出vi模式,,输入命令systemctl get-default 查看当前系统启动模式:我的是命令 ...
- python——解释型语言
编程语言分三大类 : 低级语言 . 汇编语言 . 高级语言. 现代计算机都是基于 图灵机模型 制造的. 因此计算机的内部只能接受二进制数据.而用二进制代码 0 1 描述的指令叫 ...
- flume(2)
接续上一篇:https://www.cnblogs.com/metianzing/p/9511852.html 这里也是主要记录配置文件. 以上一篇案例五为基础,考虑到日志服务器和采集日志的服务器往往 ...
- Webstorm软件快捷键
默认配置-Eclipse的常用快捷键对照表 查找/代替 Webstorm快捷键 Eclipse快捷键 说明 ctrl+shift+N ctrl+shift+R 通过文件名快速查找工程内的文件(必记) ...
- UE4使用Dll
Part1. 创建和编译Dll VS中创建Visual C++ > Win32 Console Application 工程模板,选择Dll,并勾上”Empty Project”. 在Solut ...
- 面向对象编程思想(OOP)(转发)
本文我将从面向对象编程思想是如何解决软件开发中各种疑难问题的角度,来讲述我们面向对象编程思想的理解,梳理面向对象四大基本特性.七大设计原则和23种设计模式之间的关系. 软件开发中疑难问题: 软件复杂庞 ...