• BZOJ 1082 【SCOI2005】 栅栏


    Description

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

    Input

      第一行为整数m(m<= 50)表示木材店老板可以提供多少块木材给约翰。紧跟着m行为老板提供的每一块木板的长
    度。接下来一行(即第m+2行)为整数n(n <= 1000),表示约翰需要多少木材。接下来n行表示他所需要的每一块木板
    的长度。木材的规格小于32767。(对于店老板提供的和约翰需要的每块木板,你只能使用一次)。

    Output

      只有一行,为约翰最多能够得到的符合条件的木板的个数。

     
      嗯……今天的考试题……出题人把数据一加强,卡掉无数贪心……
      看了看这道题,发现分类竟然是基础搜索题……好吧,看来我离noip还有段距离……这种题我做不出……
     
      去网上翻了翻题解,发现都是二分答案,用搜索来检验。这样复杂度虽然还是不对,但显然已经比普通的搜索好到不知道哪里去了。我以前打的二分答案都是用贪心或者dp来检验,今天还是第一次用搜索来检验。新姿势get
      于是,我们每次二分一个答案x,然后显然是尽量选小的木板,于是排序后枚举每个木板去组成什么木材。
      当然,就算这样比朴素搜索要好很多,但是不加剪枝的话显然还是过不了的。于是,仔细思考之后,可以有以下几个优化:
     
      1.当需要的木板不足最小的可以提供的木板时,显然已经没有用了,于是我们可以直接把它丢弃,并记录一下丢弃的木板总长度。当丢弃的木板和前x块木板的长度总和超过所有提供的木板的和时,可以剪掉。
      2.当两个木板长度相同时,那么交换他们组成什么木材对答案没有影响。于是我们就可以强制前面的木板去组成编号大于等于后一个的木材。
     
      加了这两个剪枝就可以过了。当然,由于原题数据水,有些贪心也是可以过的。
      下面贴代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define N 2010
    #define INF 2147483647
    
    using namespace std;
    typedef long long llg;
    
    int n,m,a[N],b[N],w[N];
    int tol,diu,l,r,mid,xu[N];
    bool ww;
    
    int getint(){
    	int w=0;bool q=0;
    	char c=getchar();
    	while((c>'9'||c<'0')&&c!='-') c=getchar();
    	if(c=='-') c=getchar(),q=1;
    	while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    	return q?-w:w;
    }
    
    void dfs(int u){
    	if(!u) ww=1;
    	if(ww || diu+w[mid]>tol) return;
    	int l=1;
    	if(b[u]==b[u+1] && u!=mid) l=xu[u+1];
    	for(int i=l;i<=n;i++)
    		if(a[i]>=b[u]){
    			xu[u]=i;
    			a[i]-=b[u]; if(a[i]<b[1]) diu+=a[i];
    			dfs(u-1);
    			if(a[i]<b[1]) diu-=a[i]; a[i]+=b[u];
    		}
    }
    
    int main(){
    	File("a");
    	n=getint();
    	for(int i=1;i<=n;i++) tol+=(a[i]=getint());
    	sort(a+1,a+n+1); m=getint();
    	for(int i=1;i<=m;i++) b[i]=getint();
    	sort(b+1,b+m+1);
    	for(int i=1;i<=m;i++) w[i]=w[i-1]+b[i];
    	l=0,r=m+1;
    	while(l!=r){
    		mid=l+r>>1; ww=0;
    		dfs(mid);
    		if(ww) l=mid+1;
    		else r=mid;
    	}
    	printf("%d",l-1);
    }
  • 相关阅读:
    nmon+python 基于AIX系统数据分析
    nmon +java nmon Alalizy agent 动态交互监控
    nomon+ pyNmonAnalyzer实现基于python的nmon监控性能数据可视化
    nmon help文档zh-han
    nmon+Java Nmon Analyser进行nmon监控数据可视化分析
    pandas 数据可视化之折线图
    nmonchart 分析.nmon监控数据成html展示
    【BZOJ4025】—二分图(线段树分治+带权并查集)
    【BZOJ4025】—二分图(线段树分治+带权并查集)
    【BZOJ2759】—一个动态树好题(LCT+Exgcd)
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/5924094.html
Copyright © 2020-2023  润新知