luoguP2329 [SCOI2005]栅栏

首先我们可以看出一个性质:取小的一定不比取大的劣.显然嘛

于是我们将约翰所需的木板从小到大排序,原材料也按从小到大排序,然后二分一个\(mid\)表示约翰取几个木板,用搜索\(check\)一下即可.

几个剪枝:

  • 一.我们可以定义一个全局变量\(Waste\)表示割下木板后总共浪费的原材料长度.

    \(\therefore\) 如果\(Waste+\sum_{i=1}^{mid}b_i>sum\),直接退出,返回\(0\).

  • 二.对于两个长度相等的所需木板,我们可以记一个\(last\)表示之前的所需木板找到了第\(last\)个,\(\therefore\)直接从\(last\)开始找即可.
  • 三.我们在二分前可以先将总和大于\(sum\)的删去,即\(while (s[r] > sum)--r;\)
#include<bits/stdc++.h>
#define il inline
#define rg register
#define gi read<int>
using namespace std;
template<class TT>
il TT read() {
    TT o = 0,fl = 1; char ch = getchar();
    while (!isdigit(ch) && ch != '-') ch = getchar();
    if (ch == '-') fl = -1, ch = getchar();
    while (isdigit(ch)) o = o * 10 + ch - '0', ch = getchar();
    return fl * o;
}
int n, m, sum, l, r, mid, t, ans, a[55], b[1005], c[55], s[1005];
bool check(int x, int last) {
    if (!x) return true;
    if (sum < t + s[mid]) return false;
    for (int i = last; i <= m; ++i) {
        if (c[i] >= b[x]) {
            c[i] -= b[x];
            if (c[i] < b[1]) t += c[i];
            if (b[x] == b[x - 1]) {
                if (check(x - 1, last)) return true;
            }
            else if (check(x - 1, 1)) return true;
            if (c[i] < b[1]) t -= c[i];
            c[i] += b[x];
        }
    }
    return false;
}
int main() {
    m = gi();
    for (int i = 1; i <= m; ++i)
        a[i] = gi(), sum += a[i];
    sort(a + 1, a + m + 1);
    n = gi();
    for (int i = 1; i <= n; ++i) b[i] = gi();
    sort(b + 1, b + n + 1);
    for (int i = 1; i <= n; ++i) s[i] = s[i - 1] + b[i];
    l = 1, r = n;
    while (s[r] > sum) --r;
    while (l <= r) {
        for (int i = 1; i <= m; ++i) c[i] = a[i];
        mid = l + r >> 1, t = 0;
        if (check(mid, 1)) ans = mid, l = mid + 1;
        else r = mid - 1;
    }
    printf("%d\n", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/lylyl/p/11762233.html

时间: 2024-10-28 14:56:34

luoguP2329 [SCOI2005]栅栏的相关文章

BZOJ1082: [SCOI2005]栅栏

1082: [SCOI2005]栅栏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1906  Solved: 816[Submit][Status][Discuss] Description 农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材.于是农夫约翰到木材店购买木材.可是木材店老板说他这里只剩下少部分大规格的木板了.不过约翰可以购买这些木板,然后切割成他所需要的规格.而且约翰有一把神奇的锯子,用它来锯木板,不会产生任

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

1082: [SCOI2005]栅栏 题目:传送门 题解: 是不是一开始在想DP?本蒟蒻也是qwq,结果很nice的错了ORZ 正解:二分+搜索 我们可以先把两种木材都进行排序,那么如果需要的最大木材比可提供的最大木材还要大的话,那么可以直接舍弃这种需要的木材. 然后就可以进入二分,如果当前可以做贡献的提供木材加起来都没有前mid块需要木材大的话,很明显当前mid不ok 返回判断值再记录答案就好了,注意一些小细节的优化 代码: 1 #include<cstdio> 2 #include<

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

http://www.lydsy.com/JudgeOnline/problem.php?id=1082 最近被这种神题虐cry...这还竟然是usaco的题QAQ我竟然如此弱....(我是不是写过这题?反正好像有点印象的样子..好像又不是..) 一开始写了个背包...贪心的找................然后造了几个数据,,wa了.. QAQ 膜拜题解.orz 首先我们得到的k个木板一定是在n个中最小的k个...(这个太显然了QAQ 我们考虑将m个提供的木材,依次从最小的放(显然先用完最短的

【bzoj1082】 SCOI2005—栅栏

http://www.lydsy.com/JudgeOnline/problem.php?id=1082 (题目链接) 题意 给出m块木柴,以及n块木板,要求将m块木柴做木板,要求将木柴切割成与木板一样的长度,问最多可以做成几块木板. Solution 今日考题.乍一看,好像可以二分,然而并不会check,于是码了个贪心,10分mdzz.. 正解:二分+搜索. 每次二分答案mid后,对每块木板进行搜索,枚举用那根木柴去进行切割.没想到剪枝这么强大,这都可以搜过去.. 剪枝1:一开始将不符合条件的

1082: [SCOI2005]栅栏

恩,看了他人的题解,才勉强理解,希望能有所收获. 思路:这道题要使用搜索+二分,可能有部分像我一样的会觉得这道题难道不是排序后一个一个去判断就可以了吗?那么这里可以举个例子! 这幅图你就会发现,如果按一个个取,就会发现只能得到2和3,但实际上6会切成2和4,3切成3,三种都会得到. 所以不是能取就切的,2应该在6那里取. 我们用回溯的方法,去看看这块木板应从哪里切,这样只要有一种情况下,能切出来就成立,二分枚举我们切前几块. 好啦,具体思路就从程序里看吧! #include<iostream>

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

对于最优解我们发现所有的最优解都可以是前多少多少个,那么我们就二分这个前多少多少个,然后用dfs去判解,我们发现在dfs的过程中如果不剪枝几乎必T,所以我们就需要一些有效的剪枝 I. 我们在枚举过程中每个数选什么是有前后顺序的,然而对于一些相同的数他们并没有顺序我们可以记录上个数的选择点,如果两数相同,那么就从上个数的选择点开始那么时间复杂度就从次方级别降到了组合数级别,是飞跃式的 II. 然后我们发现先对于枚举顺序与选择顺序的选择是玄学的,我们可以视为他们都没影响那么我们就可利用这个了,如果我

[BZOJ 1082] [SCOI2005] 栅栏 【二分 + DFS验证(有效剪枝)】

题目链接:BZOJ - 1082 题目分析 二分 + DFS验证. 二分到一个 mid ,验证能否选 mid 个根木棍,显然要选最小的 mid 根. 使用 DFS 验证,因为贪心地想一下,要尽量先用提供的小的木木棍,尽量先做出需要的大的木棍,所以要先将提供的木棍和需要的木棍都排序. DFS 的时候是按照需要的木棍从大到小的顺序一层一层搜,每一层上是按照从小到大的顺序枚举提供的木棍.(当然枚举的时候已经不一定是从小到大了,有些木棍已经被截掉了一些.) 要使用两个有效的剪枝: 1)如果下一层的木棍和

BZOJ1082: [SCOI2005]栅栏 题解

题目大意: 有一些木材,可以没有浪费地将一根木材分成几块木板(比如长度为10的木板可以切成长度为8和2的两块木板).现在你希望得到一些长度的木板,问通过分割木材最多能得到几块想要的木板. 思路: 首先,长度短的木板一定比长度长的木板容易得到,因此若要得到最多的木板,它们必定是所有木板中最短的——可以对木板排序后二分答案(用k表示). 判断是否合法就用搜索,但数据有点大,要用到两个剪枝.一个是若有一根木材被切开后剩下的长度比最短的木板还短则将其累加入waste,当waste+前k块木板的长度和>木

题目清单(更新至2016年12月17日 10:52)

若无特殊说明,默认为大视野题目 [二分答案] 2196: [Usaco2011 Mar]Brownie Slicing 1082: [SCOI2005]栅栏 3969: [WF2013]Low Power 1650: [Usaco2006 Dec]River Hopscotch 跳石子 1639: [Usaco2007 Mar]Monthly Expense 月度开支 2600: [Ioi2011]ricehub [背包类DP] 1625: [Usaco2007 Dec]宝石手镯 1531: [