1082: [SCOI2005]栅栏 二分+dfs+剪枝
2016-01-21 08:17
330 查看
首先贪心的性质是显然的,我们如果要取k个一定要取最小的k个,且尽量用最小的木材满足最大的需求,以减少浪费。
既然所取的k个是单调的,那么可以考虑二分,贪心的判断是否可行。
剪枝:
如果当前用了的+剩下所需最少的(即维护b[i]的前缀和)>所有的a。那么不可能合法,剪掉。
qwq。。只想到这一个剪枝,题解还给提供了另一个,我感觉应该用处不大吧。。。就是如果下一个和这一个相同,那么可以不从第一块木材开始搜。。
既然所取的k个是单调的,那么可以考虑二分,贪心的判断是否可行。
剪枝:
如果当前用了的+剩下所需最少的(即维护b[i]的前缀和)>所有的a。那么不可能合法,剪掉。
qwq。。只想到这一个剪枝,题解还给提供了另一个,我感觉应该用处不大吧。。。就是如果下一个和这一个相同,那么可以不从第一块木材开始搜。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,ans,rest,s; int a[55],c[55],b[1005],s0[1005]; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } bool dfs(int now,int last) { if (now<=0) return 1; if (rest+s0[now]>s) return 0; for (int i=last;i<=m;i++) if (c[i]>=b[now]) { c[i]-=b[now]; if (c[i]<b[1]) rest+=c[i]; if (b[now]==b[now-1]) { if (dfs(now-1,i)) return 1; } else { if (dfs(now-1,1)) return 1; } if (c[i]<b[1]) rest-=c[i]; c[i]+=b[now]; } return 0; } inline bool judge(int mid) { memcpy(c,a,sizeof(a)); rest=0; return dfs(mid,1); } int main() { m=read(); for (int i=1;i<=m;i++) a[i]=read(),s+=a[i]; n=read(); for (int i=1;i<=n;i++) b[i]=read(); sort(a+1,a+m+1); sort(b+1,b+n+1); for (int i=1;i<=n;i++) s0[i]=s0[i-1]+b[i]; while (s0 >s) n--; int l=0,r=n; while (l<=r) { int mid=l+r>>1; if (judge(mid)) ans=mid,l=mid+1; else r=mid-1; } cout << ans; return 0; }
相关文章推荐
- Leetcode 26 - Remove Duplicates from Sorted Array
- C++之路进阶——kmp(寻找子串位置)
- spring整合Morphia
- 安卓动画
- sqlserver 2008 查询表结构语句
- 设计模式(十七):享元模式
- 怎么可以不了解Java8 Stream
- C#中使用7Z进行压缩解压
- 设计模式学习笔记—抽象工厂模式
- bzoj 1218 [HNOI2003]激光炸弹
- 优雅的项目配置--常用库和版本管理
- Python之装饰器
- IPv6 互联网中的隐私保护和网络管理器
- 开放在线课堂平台推荐
- Leetcode 22 - Generate Parentheses
- 一键编译go文件命令.bat
- 安装go语言,配置环境及IDE,只需3步
- RDD实战
- 一周学会go语言并应用 by王奇疏
- 循环实现:将格点数据绘制在等值线上