Description

  农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材。于是农夫约翰到木材店购
买木材。可是木材店老板说他这里只剩下少部分大规格的木板了。不过约翰可以购买这些木板,然后切割成他所需
要的规格。而且约翰有一把神奇的锯子,用它来锯木板,不会产生任何损失,也就是说长度为10的木板可以切成长
度为8和2的两个木板。你的任务:给你约翰所需要的木板的规格,还有木材店老板能够给出的木材的规格,求约翰
最多能够得到多少他所需要的木板。

Input

  第一行为整数m(m<= 50)表示木材店老板可以提供多少块木材给约翰。紧跟着m行为老板提供的每一块木板的长
度。接下来一行(即第m+2行)为整数n(n <= 1000),表示约翰需要多少木材。接下来n行表示他所需要的每一块木板
的长度。木材的规格小于32767。(对于店老板提供的和约翰需要的每块木板,你只能使用一次)。

Output

  只有一行,为约翰最多能够得到的符合条件的木板的个数。

Sample Input

4
30
40
50
25
10
15
16
17
18
19
20
21
25
24
30

Sample Output

7

HINT

25切出 21 30切出 20 40切出 19、18 50切出 15、16、17

题解

二分+dfs判定

我们首先排序一下

这道题我们二分答案,再用dfs判断一下[1,mid]这段区间是否可行

我们这里是枚举木板从哪块木材上切下来(这里用倒着枚举)

但是普通的dfs判断是会T的

这里主要讲两个优化:

nlen[i]表示需要的第i块木板,now表示当前的木板的下标

1.if (nlen[now]==nlen[now-1])的时候我们直接check(now-1,i)为什么是 i 呢,因为前面小的点都被跳过了(nlen[now]都已经要第i块木材切了,nlen[now-1]和它相等当然至少要从i开始喽)

2.我们切木材当然是希望木材浪费的越少越好,所以当这块木材连第一块木板都切不下(要被浪费了),就把剩下的木材长度加到waste中

如果waste>总木材的和-sum[mid](如果mid可行的话,最优的切割waste应该是等于的)说明这样切割不是最优的

 1 #include<bits/stdc++.h>
 2 #define M 55
 3 #define N 1005
 4 using namespace std;
 5 int n,m,l,r,mid,ans,waste,sum;
 6 int len[M],tlen[M];
 7 int nlen[N],s[N];
 8 bool check(int now,int p){
 9     if (!now) return true;
10     if (waste>sum-s[mid]) return false;
11     for (int i=p;i<=m;i++)
12         if (tlen[i]>=nlen[now]){
13             tlen[i]-=nlen[now];
14             if (tlen[i]<nlen[1]) waste+=tlen[i];
15             if (nlen[now]==nlen[now-1]){
16                 if (check(now-1,i)) return true;
17             } else
18             if (check(now-1,1)) return true;
19             if (tlen[i]<nlen[1]) waste-=tlen[i];
20             tlen[i]+=nlen[now];
21         }
22     return false;
23 }
24 int main(){
25     scanf("%d",&m);
26     for (int i=1;i<=m;i++)
27         scanf("%d",&len[i]),sum+=len[i];
28     scanf("%d",&n);
29     for (int i=1;i<=n;i++)
30         scanf("%d",&nlen[i]);
31     sort(len+1,len+1+m);
32     sort(nlen+1,nlen+1+n);
33     for (int i=1;i<=n;i++)
34         s[i]=s[i-1]+nlen[i];
35     l=0; r=n;
36     while (l<=r){
37         mid=(l+r)>>1;
38         waste=0;
39         memcpy(tlen,len,sizeof(len));
40         if (check(mid,1)){
41             ans=mid; l=mid+1;
42         } else r=mid-1;
43     }
44     printf("%d\n",ans);
45     return 0;
46 }

View Code

转载于:https://www.cnblogs.com/zhuchenrui/p/7622748.html

BZOJ-1082-[SCOI2005]栅栏(二分+dfs判定)相关推荐

  1. bzoj 1082: [SCOI2005]栅栏(二分+DFS)

    1082: [SCOI2005]栅栏 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2373  Solved: 1007 [Submit][Stat ...

  2. BZOJ【1082】栅栏

    1082: [SCOI2005]栅栏 Time Limit: 10 Sec Memory Limit: 162 MB Description 农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些 ...

  3. BZOJ1082: [SCOI2005]栅栏

    1082: [SCOI2005]栅栏 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1906  Solved: 816 [Submit][Statu ...

  4. [SCOI2005]栅栏(贪心+二分+dfs)难度⭐⭐⭐⭐

    [SCOI2005]栅栏(贪心+二分+dfs) P2329 [SCOI2005]栅栏 题目描述 农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材.于是农夫约翰到木材店购买木材. ...

  5. BZOJ 1087: [SCOI2005]互不侵犯King

    二次联通门 : BZOJ 1087: [SCOI2005]互不侵犯King /*BZOJ 1087: [SCOI2005]互不侵犯King状压dp将每一行棋子的存在状态压成一个整数f[i][j][k] ...

  6. 51nod1307(暴力树剖/二分dfs/并查集)

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307 题意: 中文题诶~ 思路: 解法1:暴力树剖 用一个数 ...

  7. 第四届河南省程序设计大赛D nyoj306-走迷宫【二分DFS、最短路Dijkstra】

    Dr.Kong设计的机器人卡多非常爱玩,它常常偷偷跑出实验室,在某个游乐场玩之不疲.这天卡多又跑出来了,在SJTL游乐场玩个不停,坐完碰碰车,又玩滑滑梯,这时卡多又走入一个迷宫.整个迷宫是用一个N * ...

  8. 数据结构 | 折半查找 /二分查找 算法细节、二分查找判定树

    一.基本思想 假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步 ...

  9. bzoj 1086: [SCOI2005]王室联邦(DFS)

    1086: [SCOI2005]王室联邦 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 2100  Solved ...

最新文章

  1. Java开发环境的搭建以及使用eclipse从头一步步创建java项目
  2. CentOS 6.5 安装与配置LAMP
  3. visual studio 2019、2017、2015下载网址
  4. 基于顺序存储结构的图书信息表的修改(C++)
  5. python print(len(pi_string))_Python如何从文件中读取数据
  6. jenkins启动/重启/停止命令 改端口
  7. Android 系统(176)---Android多线程
  8. linux内存管理(十一)-页回收总览
  9. java代码逆向工程生成uml
  10. 正则表达式-2-正则表达式实战1
  11. Xshell上传文件到Centos服务器
  12. OPENSTACK-210-3-配置网络(Configure networking)-命令行
  13. ibm最早的个人计算机,个人计算机竞争者分析:IBM.pdf
  14. java斗地主发牌教学,命令行版的斗地主你玩过没?
  15. 技能篇:开发必备linux命令大全
  16. Qt电子白板 画板 画笔 毛笔 钢笔 蜡笔 2D/3D图形 音视频播放
  17. windows 快捷键(基本快捷键)
  18. 【USACO1.2_1】★Milking Cows 挤牛奶
  19. RegressionTSS=ESS+RSS
  20. onlyoffice+vue集成

热门文章

  1. GDCM:gdcm::IOD的测试程序
  2. GDCM:制作模板的测试程序
  3. Boost:bimap双图修改的测试程序
  4. Boost:aligned alloc对齐分配的测试程序
  5. ITK:二进制图像的最小和最大曲率流
  6. VTK:可视化算法之HeadSlice
  7. VTK:可视化之TransformActorCollection
  8. c++Cocktail Selection Sort鸡尾酒选择排序的实现算法(附完整源码)
  9. C语言将不固定的表达式转换为后缀表达式(附完整源码)
  10. c++冒泡排序(附完整源码)