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


    http://www.lydsy.com/JudgeOnline/problem.php?id=1082

    题意:n个给出木板,m个给出木板。可以将那m个木板锯成泥想要的长度。问最大能锯成多少个给出的n个木板。(n<=1000, m<=50)

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long ll;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define error(x) (!(x)?puts("error"):0)
    #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    
    const int N=2005;
    int v[N], n, m, w[N], sum[N], c[N], tot, rest;
    
    bool dfs(int dep, int last) {
    	if(!dep) return true;
    	if(rest+sum[dep]>tot) return false;
    	for1(i, last, n) {
    		if(c[i]>=w[dep]) {
    			c[i]-=w[dep];
    			if(c[i]<w[1]) rest+=c[i];
    			if(w[dep]==w[dep-1]) { if(dfs(dep-1, i)) return true; }
    			else if(dfs(dep-1, 1)) return true;
    			if(c[i]<w[1]) rest-=c[i];
    			c[i]+=w[dep];
    		}
    	}
    	return false;
    }
    bool check(int d) {
    	memcpy(c, v, sizeof(int)*(n+1));
    	rest=0;
    	return dfs(d, 1);
    }
    int main() {
    	read(n);
    	for1(i, 1, n) read(v[i]), tot+=v[i];
    	sort(v+1, v+1+n);
    	read(m);
    	for1(i, 1, m) read(w[i]);
    	sort(w+1, w+1+m);
    	for1(i, 1, m) sum[i]=sum[i-1]+w[i];
    	while(sum[m]>tot) --m;
    	int l=0, r=m, mid;
    	while(l<=r) {
    		mid=(l+r)>>1;
    		if(check(mid)) l=mid+1;
    		else r=mid-1;
    	}
    	print(l-1);
    	return 0;
    }


    最近被这种神题虐cry。。。这还竟然是usaco的题QAQ我竟然如此弱。。。。(我是不是写过这题?反正好像有点印象的样子。。好像又不是。。)

    一开始写了个背包。。。贪心的找。。。。。。。。。。。。。。。。然后造了几个数据,,wa了。。

    QAQ

    膜拜题解。orz

    首先我们得到的k个木板一定是在n个中最小的k个。。。(这个太显然了QAQ

    我们考虑将m个提供的木材,依次从最小的放(显然先用完最短的。。。)

    所以将k个木板和m个提供的木材排序后再做。。。。。

    二分k,判定是否能得到。。。

    那么就是暴力枚举前k个的放法,可是。。2^1000。。。。tle成翔。。。。。。。。

    倒序枚举

    那么考虑剪枝orz

    首先如果当一个提供的木材小于了最小的所需木板,那么我们用个rest累加,当rest+sum[k]>tot时,剪掉(sum[k]表示前k个所需木板长度,tot表示提供木板的总量(其实这个剪枝还不够呢。。。因为tot是静态的,并没有变动。。。反正不改也能a))

    然后继续剪枝,当k木板等于k-1木板的长度,那么我们不需要从1枚举木材了,因为此时k木板从哪个枚举说明前面的都不够了。。所以直接从k木板当前的木材枚举k-1。。

    然后能水过了。。

  • 相关阅读:
    Linux 的伪终端的基本原理 及其在远程登录(SSH,telnet等)中的应用
    入住cnblogs第一篇随笔 Hello, world!
    清除maven加载失败的jar包记录
    解决Jackson2反序列化LocalDateTime报错
    springboot+dubbo基于zookeeper快速搭建一个demo
    解决bug:sprongboot2整合shiro,swagger2页面样式加载不出来问题
    Tomcat 8启动速度慢原因1: At least one JAR was scanned for TLDs yet contained no TLDs
    解决exlicpe以debug模式启动或运行速度非常慢的问题
    MAVEN打包报错:com.sun.net.ssl.internal.ssl;sun.misc.BASE64Decoder;程序包 javax.crypto不存在处理办法
    SQL根据B表内容修改A表内容,查询表中重复记录,删除掉重复项只保留一条
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4160961.html
Copyright © 2020-2023  润新知