[BZOJ 1082] [SCOI2005] 栅栏 【二分 + DFS验证(有效剪枝)】
题目链接:BZOJ - 1082
题目分析
二分 + DFS验证。
二分到一个 mid ,验证能否选 mid 个根木棍,显然要选最小的 mid 根。
使用 DFS 验证,因为贪心地想一下,要尽量先用提供的小的木木棍,尽量先做出需要的大的木棍,所以要先将提供的木棍和需要的木棍都排序。
DFS 的时候是按照需要的木棍从大到小的顺序一层一层搜,每一层上是按照从小到大的顺序枚举提供的木棍。(当然枚举的时候已经不一定是从小到大了,有些木棍已经被截掉了一些。)
要使用两个有效的剪枝:
1)如果下一层的木棍和这一层的木棍等长,就从这一层木棍枚举到的提供的木棍开始枚举,因为前面的都是不可以的。
2)当一根木棍被截掉一段之后小于最小的需要的木棍,那么它就废掉了,记录当前废掉的木棍总长Rest,如果Rest + 1到mid所有木棍的总长 > 提供的所有木棍总长,那么就返回 false。
代码
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath> using namespace std; const int MaxM = 50 + 5, MaxN = 1000 + 5; int n, m, Ans, Rest, Need, Tot;
int A[MaxM], B[MaxN], Sum[MaxN]; bool DFS(int x, int y)
{
if (Rest + Need > Tot) return false;
bool ret = false;
for (int i = y; i <= m; ++i)
{
if (A[i] >= B[x])
{
A[i] -= B[x];
if (A[i] < B[1]) Rest += A[i];
if (x == 1) ret = true;
else if (B[x - 1] == B[x]) ret = DFS(x - 1, i);
else ret = DFS(x - 1, 1);
Rest -= A[i];
A[i] += B[x];
if (ret) return true;
}
}
return false;
} int main()
{
scanf("%d", &m);
for (int i = 1; i <= m; ++i) scanf("%d", &A[i]);
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &B[i]);
sort(A + 1, A + m + 1);
for (int i = 1; i <= m; ++i) Tot += A[i];
sort(B + 1, B + n + 1);
for (int i = 1; i <= n; ++i) Sum[i] = Sum[i - 1] + B[i];
int l, r, mid;
l = 0; r = n;
Ans = 0;
while (l <= r)
{
mid = (l + r) >> 1;
Need = Sum[mid];
Rest = 0;
if (DFS(mid, 1))
{
Ans = mid;
l = mid + 1;
}
else r = mid - 1;
}
printf("%d\n", Ans);
return 0;
}
[BZOJ 1082] [SCOI2005] 栅栏 【二分 + DFS验证(有效剪枝)】的更多相关文章
- bzoj 1082: [SCOI2005]栅栏 题解
1082: [SCOI2005]栅栏 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2340 Solved: 991[Submit][Status] ...
- 【BZOJ 1082】[SCOI2005]栅栏 二分+dfs
对于最优解我们发现所有的最优解都可以是前多少多少个,那么我们就二分这个前多少多少个,然后用dfs去判解,我们发现在dfs的过程中如果不剪枝几乎必T,所以我们就需要一些有效的剪枝 I. 我们在枚举过程中 ...
- bzoj 1082: [SCOI2005]栅栏【二分+dfs】
二分答案,dfs判断是否可行,当b[k]==b[k-1]时可以剪枝也就是后移枚举位置 #include<iostream> #include<cstdio> #include& ...
- bzoj 1082: [SCOI2005]栅栏
Description 农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材.于是农夫约翰到木材店购 买木材.可是木材店老板说他这里只剩下少部分大规格的木板了.不过约翰可以购买这些 ...
- [SCOI2005]栅栏 二分+dfs
这个题真的是太nb了,各种骚 二分答案,肯定要减最小的mid个,从大往小搜每一个木板,从大往小枚举所用的木材 当当前木材比最短的木板还短,就扔到垃圾堆里,并记录waste,当 waste+sum> ...
- bzoj1082: [SCOI2005]栅栏(二分答案搜索判断)
1082: [SCOI2005]栅栏 题目:传送门 题解: 是不是一开始在想DP?本蒟蒻也是qwq,结果很nice的错了ORZ 正解:二分+搜索 我们可以先把两种木材都进行排序,那么如果需要的最大木材 ...
- [BZOJ1082][SCOI2005]栅栏 二分+搜索减枝
1082: [SCOI2005]栅栏 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2430 Solved: 1034[Submit][Status ...
- Bzoj 1085: [SCOI2005]骑士精神 (dfs)
Bzoj 1085: [SCOI2005]骑士精神 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 dfs + 剪枝. 剪枝方法: ...
- 1082: [SCOI2005]栅栏
链接 思路 二分+搜索+剪枝. 首先二分一个答案,表示最多可以切出x块.(一个结论:切出的一定是从较小的前x块.如果一个木材可以满足很多个需要的木材,那么切出最小的,就意味着以后再选时的机会更多.) ...
随机推荐
- POJ 1185 炮兵
是中国标题.大家都说水问题.但是,良好的1A它? 标题效果: 给出n*m的矩阵,当某个单元格有炮兵部队时它的上下左右两格(不包含斜着的方向)是这支部队的攻击范围.问在两支部队之间不可能相互攻击到的情况 ...
- hdu2058java
The sum problem Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- oracle授权另外一个用户访问自己创建的数据对象
oracle安装好之后,有一个默认的scott用户,该用户有一个默认的emp表,怎样让新创建的用户也能够访问这个表呢? 授权xiaoming这个用户访问emp表,但是xiaoming只有select权 ...
- Java Stax操作XML简介
使用stax操作xml 非常的简单,它的读取过程像是一个光标在移动.针对不同的节点做不同的处理. 先看一个基于光标的模型处理xml: public class StaxTest { @Test pub ...
- Windows2012中Python2.7.11+Python3.4.4+Pycharm
下载软件包 Python2.7.11: https://www.python.org/ftp/python/2.7.11/python-2.7.11.amd64.msi Python3.4.4: ...
- CSS相对定位、绝对定位
CSS定位属性:position. 定位的基本思想:定义元素框相对于其正常位置应该出现的位置,或者相对于父元素.另一个元素或浏览器窗口本身的位置. position属性值:static.relativ ...
- Node.js + Express + Mongodb 开发搭建个人网站(二)
二.路由 1.打开 routes/index.js ,这个意思就是 捕获到访问主页的get请求: 并通过 app.js 分配到对应的路由里: 看到这里,打开 http://127.0.0.1:300 ...
- 【基础】Oracle 表空间和数据文件
多个表空间的优势:1.能够将数据字典与用户数据分离出来,避免由于字典对象和用户对象保存在同一个数据文件中而产生的I/O冲突2.能够将回退数据与用户数据分离出来,避免由于硬盘损坏而导致永久性的数据丢失3 ...
- 【STL】string 常用函数
string类的构造函数: string(const char *s); //用c字符串s初始化 string(int n,char c); //用n个字符c初始化 此外,string类还支持默认构造 ...
- CorAnimation7-高效绘图、图像IO以及图层性能
高效绘图 软件绘图 术语绘图通常在Core Animation的上下文中指代软件绘图(意即:不由GPU协助的绘图).在iOS中,软件绘图通常是由Core Graphics框架完成来完成.但是,在一些必 ...