• BZOJ1082 [SCOI2005]栅栏


    最近做做搜索题吧。。。^_^

    然后又被虐了。。。T T

    这还是一道usaco题。。。我去。。。

    为了方便叙述,FJ买的叫"木块",要被切掉的叫"木材"!!!(我也是醉了0.0)

    根据贪心,我们肯定先搞到小的木块。。。于是先对要买的木块进行排序,然后二分答案

    之后如何判断:

    裸的dfs肯定过不掉T T,考虑优化

    (1)如果两块木块长度相同,第一个已经被dfs过了且从第x块木材上被切下来,则第二个也至少要从第x块木材上切。(貌似是对称性原理的说。。。)

    (2)某巨巨:"用waste表示每一个已经裁过的木材浪费的木材和,所谓浪费的木材就是最小的木块都比它大,那么他当前就已经裁不出任何木块了。就把这个木材加到waste去,如果waste>木材和-s[mid],说明这样裁木材是错误的,所以减枝。"

    两个优化使得搜索速度快的飞起!!!

     1 /**************************************************************
     2     Problem: 1082
     3     User: rausen
     4     Language: C++
     5     Result: Accepted
     6     Time:4 ms
     7     Memory:820 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 #include <cstring>
    12 #include <algorithm>
    13  
    14 using namespace std;
    15 const int N = 1005;
    16 int n, m, waste, l, r, mid;
    17 int a[N], b[N], c[N], s[N], T;
    18  
    19 inline int read(){
    20     int x = 0;
    21     char ch = getchar();
    22     while (ch < '0' || ch > '9')
    23         ch = getchar();
    24  
    25     while (ch >= '0' && ch <= '9'){
    26         x = x * 10 + ch - '0';
    27         ch = getchar();
    28     }
    29     return x;
    30 }
    31  
    32 bool dfs(int x, int pos){
    33     if (!x) return 1;
    34     if (s[mid] + waste > T) return 0;
    35     for (int i = pos; i <= m; ++i)
    36         if (c[i] >= b[x]){
    37             c[i] -= b[x];
    38             if (c[i] < b[1])
    39                 waste += c[i];
    40             if (b[x] == b[x - 1]){
    41                 if (dfs(x - 1, i))
    42                     return 1;
    43             }
    44             else if (dfs(x - 1, 1)) return 1;
    45             if (c[i] < b[1]) waste -= c[i];
    46             c[i] += b[x];
    47         }
    48     return 0;
    49 }
    50  
    51 int main(){
    52     m = read();
    53     for (int i = 1; i <= m; ++i)
    54         a[i] = read(), T += a[i];
    55     n = read();
    56     for (int i = 1; i <= n; ++i)
    57         b[i] = read();
    58     sort(a + 1, a + m + 1);
    59     sort(b + 1, b + n + 1);
    60     for (int i = 1; i <= n; ++i)
    61         s[i] = s[i - 1] + b[i];
    62     while (s[n] > T) --n;
    63     l = 0, r = n + 1;
    64     while (l + 1 < r){
    65         waste = 0;
    66         memcpy(c, a, sizeof(a));
    67         mid = l + r >> 1;
    68         if (dfs(mid, 1)) l = mid;
    69         else r = mid;
    70     }
    71     printf("%d
    ", l);
    72     return 0;
    73 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    WPF 快捷键读写txt
    win10 UWP GET Post
    win10 UWP GET Post
    win10 UWP Hmac
    win10 UWP Hmac
    win10 UWP MessageDialog 和 ContentDialog
    MySQL 触发器-更新字段时,status列会加一
    [SDOI2018]旧试题
    win10 UWP MessageDialog 和 ContentDialog
    win10 UWP RSS阅读器
  • 原文地址:https://www.cnblogs.com/rausen/p/4057888.html
Copyright © 2020-2023  润新知