• 【BZOJ1082】【SCOI2005】栅栏


    暴力出奇迹……

    原题:

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

    m<= 50,n <= 1000

    第一眼就脑补出暴力做法二分+dfs,然而想了想觉得dfs的复杂度非常不大丈夫啊

    然后搜题解,就是dfs……
    首先需要的木条递增排序然后降序dfs,对于每次搜到的木条遍历所有大木条

    两个剪枝

    搞个前缀和s[i]表示从第1到第i个需要的木条的长度和,用tot表示提供的木条的总长度,如果某个大木条剩下的部分比需要的最小的木条还短,这个大木条就相当于浪费掉了,加到一个waste里面,如果某层dfs中dfs到的木条的前缀和+waste比tot大,就直接return

    如果当前木条和下一层要dfs到的木条长度一样,下一层搜的时候就直接从当前木条使用的大木条往后遍历(如果不一样就只能从1开始遍历了

    然后这样剪枝直接把复杂度50^1000的dfs_1s跑过了……
    暴力出奇迹……

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 int rd(){int z=0,mk=1;  char ch=getchar();
     7     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
     8     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
     9     return z*mk;
    10 }
    11 int n,m;  int a[1100],b[1100];
    12 int wst=0,s[1100],tt=0,p;
    13 bool dfs(int x,int y){
    14     if(!x)  return true;
    15     if(wst+s[p]>tt)  return false;
    16     bool flg;
    17     for(int i=y;i<=n;++i)if(a[i]>=b[x]){
    18         a[i]-=b[x];
    19         if(a[i]<b[1])  wst+=a[i];
    20         flg=dfs(x-1,(b[x]==b[x-1] ? i : 1));
    21         if(a[i]<b[1])  wst-=a[i];
    22         a[i]+=b[x];
    23         if(flg)  return true;
    24     }
    25     return flg;
    26 }
    27 int bnrsch(int l,int r){
    28     int md;
    29     while(l+1<r){  md=(l+r)>>1;  (dfs(p=md,1) ? l : r)=md;}
    30     return dfs(r,1) ? r : l;
    31 }
    32 int main(){//freopen("ddd.in","r",stdin);
    33     cin>>n;
    34     for(int i=1;i<=n;++i)  tt+=(a[i]=rd());
    35     sort(a+1,a+n+1);
    36     cin>>m;
    37     int mn=0,mx=m;
    38     for(int i=1;i<=m;++i)  b[i]=rd();
    39     sort(b+1,b+m+1);
    40     for(int i=1;i<=m;++i){
    41         s[i]=s[i-1]+b[i];
    42         mn+=(a[i]>b[i]);  if(s[i]>tt)  mx=min(mx,i-1);
    43     }
    44     cout<<bnrsch(mn,mx)<<endl;
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    linux命令学习之:cd
    SSH原理与运用
    java遍历当前会话所有Session
    spring+quartz报错:Table 'XXXX.QRTZ_TRIGGERS' doesn't exist
    python检测编码
    python安装模块
    python网络爬虫
    系统编码 python编码
    python 中文路径
    python读取文件乱码
  • 原文地址:https://www.cnblogs.com/JSL2018/p/6526190.html
Copyright © 2020-2023  润新知