题目链接: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验证(有效剪枝)】的更多相关文章

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

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

  2. 【BZOJ 1082】[SCOI2005]栅栏 二分+dfs

    对于最优解我们发现所有的最优解都可以是前多少多少个,那么我们就二分这个前多少多少个,然后用dfs去判解,我们发现在dfs的过程中如果不剪枝几乎必T,所以我们就需要一些有效的剪枝 I. 我们在枚举过程中 ...

  3. bzoj 1082: [SCOI2005]栅栏【二分+dfs】

    二分答案,dfs判断是否可行,当b[k]==b[k-1]时可以剪枝也就是后移枚举位置 #include<iostream> #include<cstdio> #include& ...

  4. bzoj 1082: [SCOI2005]栅栏

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

  5. [SCOI2005]栅栏 二分+dfs

    这个题真的是太nb了,各种骚 二分答案,肯定要减最小的mid个,从大往小搜每一个木板,从大往小枚举所用的木材 当当前木材比最短的木板还短,就扔到垃圾堆里,并记录waste,当 waste+sum> ...

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

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

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

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

  8. Bzoj 1085: [SCOI2005]骑士精神 (dfs)

    Bzoj 1085: [SCOI2005]骑士精神 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 dfs + 剪枝. 剪枝方法: ...

  9. 1082: [SCOI2005]栅栏

    链接 思路 二分+搜索+剪枝. 首先二分一个答案,表示最多可以切出x块.(一个结论:切出的一定是从较小的前x块.如果一个木材可以满足很多个需要的木材,那么切出最小的,就意味着以后再选时的机会更多.) ...

随机推荐

  1. TCP/IP 编程

    http://www.cnblogs.com/ggjucheng/archive/2012/08/18/2645324.html

  2. Linux shell的&&和||--转载

    Linux shell的&&和||   shell 在执行某个命令的时候,会返回一个返回值,该返回值保存在 shell 变量 $? 中.当 $? == 0 时,表示执行成功:当 $? ...

  3. &&与&

    if((2>1)&&(4>3))System.out.printf("两边都是true"); else   System.out.println(&qu ...

  4. PHP5常量

    用函数 define()设置常量 define函数有3个参数 1.必选,常量的名称,标识符 2.必选,常量的值 3.可选,默认不设置,常量名称大小写敏感.如果设置true,常量名称不区分大小写! 下面 ...

  5. centos7安装chrome的历程(fedora同)

    安装 首先是下载,地址奉上:http://www.google.cn/chrome/browser/desktop/index.html,选择64 bit .rpm (适用于 Fedora/openS ...

  6. GitHub安装失败

    安装GitHub客户端的时候,会提示失败,如下: An error occurred trying to download 'http://github-windows.s3.amazonaws.co ...

  7. Oracle 特殊字符模糊查询的方法

    最近在写DAO层的时候,遇到一个问题,就是使用like进行模糊查询时,输入下划线,无法精确查到数据,而是返回所有的数据. 这让我很好奇,百度之后才发现,原来是因为有些特殊字符需要进行转义才可以进行查询 ...

  8. Oracle存储过程中不支持DML语言的解决方法(针对遇见的DROP关键字)

    ---存储过程中的原语句: ---删除表 DROP TABLE A_NEWTDDATA; --报错 经查询:存储过程不支持DML语言: 解决方法: execute immediate 'DROP TA ...

  9. ECshop--搜索模块细究

    ecshop细究 今天看了下ecshop搜索这块,前台数据一直到后台查询再返回前台.大致是这么个过程,首先,在index.dwt文件内,body下面引入了 <!-- #BeginLibraryI ...

  10. UML图基本类型

    use case model用例模型 analysiss model分析模型 design model设计模型 implementation model实现模型 deployment model部署模 ...