当前位置: 首页 > news >正文

【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。。

然后能水过了。。

相关文章:

  • magento Mage custom helper not found
  • 通过递归组合多维数组!
  • 95th percentile concentration
  • 用oracle查询当前数据库中的所有表
  • Node图文教程(第四章:express)
  • ArcGIS查找空洞多边形
  • ARC066E/AtCoder2273 Addition and Subtraction Hard
  • 源代码管理工具 ——Github的介绍与简要教程
  • 关于MFLAGS与MAKEFLAGS
  • Linux下的nexus数据迁移
  • windows下安装memcached
  • 添加本地缓存功能
  • 组策略管理——软件限制策略(1)
  • Python学习教程(Python学习路线):10个必备的爬虫工具
  • 区块链Oracle原理及实现
  • Google 是如何开发 Web 框架的
  • JavaScript-如何实现克隆(clone)函数
  • Java多线程(4):使用线程池执行定时任务
  • MySQL主从复制读写分离及奇怪的问题
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • STAR法则
  • Vue小说阅读器(仿追书神器)
  • 从重复到重用
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 为什么要用IPython/Jupyter?
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • scrapy中间件源码分析及常用中间件大全
  • ​2020 年大前端技术趋势解读
  • #162 (Div. 2)
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (转)平衡树
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .FileZilla的使用和主动模式被动模式介绍
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET Core引入性能分析引导优化
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(二)...
  • .net6使用Sejil可视化日志
  • .NET处理HTTP请求
  • .Net中的集合
  • /var/lib/dpkg/lock 锁定问题
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?
  • [ C++ ] STL priority_queue(优先级队列)使用及其底层模拟实现,容器适配器,deque(双端队列)原理了解
  • [ 第一章] JavaScript 简史
  • [2]十道算法题【Java实现】
  • [Android]使用Git将项目提交到GitHub
  • [CLR via C#]11. 事件