简要题意

木材店老板给出一个整数 \(m\) 和 \(m\) 个木板的长度。老板给出的木板可以随意无损耗切割。

约翰给出一个整数 \(n\) 和所需要的 \(n\) 个木板的长度。

求约翰能得到最多木板的个数。

分析

二分答案的题基本不会是单纯的二分,一般会带上一些优化、DP、搜索等……

这道题主要是运用搜索和剪枝,而且剪枝不止一个。

正常搜索肯定都会写,不过优化比较多。

优化一:贪心

既然木材店的木板都可以任意分割,那么将给出的 m 个木板排序,优先使用长木板。

而对于需要的木板来说,优先使用短木板才能使木板数量最大。

优化二:前缀和

用前缀和维护所需木板长度,记录给出木板总长度。

二分前判断所需木板总长度是否已经大于给出木板总长度,超过就向回退,直到木板足够。

优化三:剪枝一

记录浪费的木材数量。一块长木板被切割后,不使用的那段就可能被浪费。

搜索过程中,如果浪费掉的木材长度与所需木材的长度超过了给出木材总长度,则不继续向下搜索。

优化四:剪枝二

如果需要的两块相邻木板长度相等,我们就可以从上一次放的那一块枚举,可以节省大量计算。

Code

来自 Trump 的 Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring> using namespace std; int n,m,g_wo[1145140],n_wo[1145140],pre[1145140];
int tot,mid,waste; bool check( int num , int le ) {
//num 还需要的木材数量 le 左边界
if ( num == 0 ) return true;//全可以取到则返回true
if ( pre[mid] + waste > tot ) {
//优化3
//若需要的木板长度和浪费长度加起来超过老板提供总长度
return false;
}
for ( int i = le; i <= n; ++i) {
if ( g_wo[i] >= n_wo[num] ) {
bool k;
//g_wo[i]的长度大 可以锯下来n_wo[num]的长度
g_wo[i] -= n_wo[num];
//则先锯下来 方便向前遍历 一会儿回溯
if ( g_wo[i] < n_wo[1] ) {
//剩下的木材若连第一个(最短的)需要木板的长度都没有
waste += g_wo[i];//则是无法使用的废料
}
if ( n_wo[num] == n_wo[num - 1] ) {
//优化4
k = check( num - 1 , i );
//num - 1只用从i开始搜就行
//因为是降序排列,所以num - 1一定小于等于num表示的长度
//若num前一个与num需要木材长度一样
//则num - 1的长度一定大于i之前的提供木板的长度
//所以直接从i开始向后找
}
else k = check( num - 1 , 1 );
if ( g_wo[i] < n_wo[1] ) {
waste -= g_wo[i];
//回溯
//前面因为是先减n_wo[1]再判断
//所以这里的判断要先进行
}
g_wo[i] += n_wo[num];//回溯
if ( k == true ) return true;
//入果已经有可能则直接返回ture
}
}
return false;
} int main() {
scanf("%d",&m);
for (int i = 1; i <= m; ++i) {
scanf("%d",&g_wo[i]);//提供的木材
tot += g_wo[i];
}
scanf("%d",&n);
for (int i = 1; i <= n; ++i) {
scanf("%d",&n_wo[i]);//需要的木材
}
sort( g_wo + 1 , g_wo + 1 + m );
sort( n_wo + 1 , n_wo + 1 + n );
//优化1
for (int i = 1; i <= n; ++i) {
pre[i] = n_wo[i];
pre[i] += pre[i - 1];//前缀和
}//优化2
int l_an = 0,r_an = n;//表示最多的木板数
while ( r_an > 0 && pre[r_an] > tot ) {
r_an --;//若需要的长度大于提供长度
}
while ( l_an <= r_an ) {//正常二分
waste = 0;//记得初始化QWQ
mid = l_an + ( ( r_an - l_an ) >> 1 );
if ( check( mid , 1 ) ) l_an = mid + 1;
else r_an = mid - 1;
}
//输出r是因为在l = r的情况下,若mid可取,则l会变成mid+1但r不变
//若不可取则r会向前-1
printf("%d\n",r_an);
//二分答案一般二分的都是让输出的内容
return 0;
}

总结

总的来说,这道题是以搜索为辅的二分答案,重点是优化很多。

经过一段时间思考想出了前两个优化,优化三四没想出来。

这道题提供了一种新的类型的节省计算的方法,还是很有价值的。

[SCOI2005] 栅栏【题解】的更多相关文章

  1. bzoj 1082: [SCOI2005]栅栏 题解

    1082: [SCOI2005]栅栏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2340  Solved: 991[Submit][Status] ...

  2. BZOJ1082: [SCOI2005]栅栏 题解

    题目大意: 有一些木材,可以没有浪费地将一根木材分成几块木板(比如长度为10的木板可以切成长度为8和2的两块木板).现在你希望得到一些长度的木板,问通过分割木材最多能得到几块想要的木板. 思路: 首先 ...

  3. 【BZOJ1082】[SCOI2005]栅栏(搜索)

    [BZOJ1082][SCOI2005]栅栏(搜索) 题面 BZOJ 洛谷 题解 随便写个爆搜,洛谷上就\(80\)分了.先放爆搜代码: #include<iostream> #inclu ...

  4. bzoj1082: [SCOI2005]栅栏(二分答案搜索判断)

    1082: [SCOI2005]栅栏 题目:传送门 题解: 是不是一开始在想DP?本蒟蒻也是qwq,结果很nice的错了ORZ 正解:二分+搜索 我们可以先把两种木材都进行排序,那么如果需要的最大木材 ...

  5. 洛谷 P2329 [SCOI2005]栅栏 解题报告

    P2329 [SCOI2005]栅栏 题目描述 农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材.于是农夫约翰到木材店购买木材.可是木材店老板说他这里只剩下少部分大规格的木板了 ...

  6. [BZOJ1082][SCOI2005]栅栏 二分+搜索减枝

    1082: [SCOI2005]栅栏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2430  Solved: 1034[Submit][Status ...

  7. SCOI2005栅栏

    Description 农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材.于是农夫约翰到木材店购买木材.可是木材店老板说他这里只剩下少部分大规格的木板了.不过约翰可以购买这些木 ...

  8. bzoj1082[SCOI2005]栅栏

    Description 农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材.于是农夫约翰到木材店购 买木材.可是木材店老板说他这里只剩下少部分大规格的木板了.不过约翰可以购买这些 ...

  9. 【BZOJ】1082: [SCOI2005]栅栏(二分+dfs)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1082 题意:n个给出木板,m个给出木板.可以将那m个木板锯成泥想要的长度.问最大能锯成多少个给出的n ...

  10. bzoj 1082: [SCOI2005]栅栏

    Description 农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材.于是农夫约翰到木材店购 买木材.可是木材店老板说他这里只剩下少部分大规格的木板了.不过约翰可以购买这些 ...

随机推荐

  1. Go/Python RPC使用

    Remote Procedure Call 简单RPC调用 server实现 // 注册接口 type HelloService struct{} func (s *HelloService) Hel ...

  2. 快速上手Linux核心命令(三):文件和目录操作命令

    @ 目录 前言 cd 切换目录 pwd 显示当前路径 ls 显示目录下内容及相关属性信息 mkdir 创建目录 tree 以树形结构显示目录下的内容 touch 创建空白文件或改变文件的时间戳属性 c ...

  3. LINUX经常使用的命令详解

    LINUX经常使用的命令详解 源地址:http://blog.itpub.net/29065182/viewspace-1189162/ 1.man 对你熟悉或不熟悉的命令提供帮助解释  eg:man ...

  4. CF1808E Minibuses on Venus 智商毁灭记

    都要考省选了大脑还在这里下线 场上看到这道题很快推出了 \(k\) 为奇数的搞法,发现可以直接做到 \(O(k\log n)\),一阵狂喜然后肝起了 E3,结果 E1 都没过. 事实上这道题可以直接做 ...

  5. 2022-01-05:有四种诗的韵律分别为: AABB、ABAB、ABBA、AAAA。 比如 : 1 1 3 3就属于AABB型的韵律、

    2022-01-05:有四种诗的韵律分别为: AABB.ABAB.ABBA.AAAA. 比如 : 1 1 3 3就属于AABB型的韵律.6 6 6 6就属于AAAA型的韵律等等, 一个数组arr,当然 ...

  6. Spring源码:Bean生命周期(终章)

    前言 本系列前面讲解了Spring的bean定义.bean实例化.bean初始化等生命周期.这些步骤使我们能够了解bean从创建到准备好使用所经历的过程.但是,除了这些步骤,bean的销毁也是非常重要 ...

  7. flutter填坑之旅(环境搭建篇--mac系统)

    上次配置过Mac到flutter环境,但是由于最近系统更新了,什么都没了又得从新配置,发现自己竟然好多都忘记了,看来还是得把它记下来才行 在Mac上安装并运行Flutter 最低要求: 操作系统:ma ...

  8. mac -bash: ls: No such file or directory

    再mac 输入ls 竟然提示我 如图其他到命令都不能用了??? 网上找了大半天.看见这种类似的很多,但是最后都不是我要的答案,最后没辙,注销用户,重新登陆,问题没有了,也不知道是不是mac的bug:有 ...

  9. 【.NET源码解读】Configuration组件及自动更新

    Configuration组件是.NET中一个核心的.非常重要的组件.它提供了一种方便的机制,用于从配置文件.环境变量.命令行参数等各种数据源中读取和配置应用程序,以满足不同环境下应用程序的需求. 在 ...

  10. Java发展史、JDK环境配置、运行原理及开发工具(学习的前期准备)

    一.Java的历史和三大版本 1.Java的发展史 Java由sun公司开发,Java之父James Gosling,Java是一门面向对象的编程语言,也称为"高级编程语言" Ja ...