bzoj1082[SCOI2005]栅栏
2016-08-15 17:42
253 查看
Description
农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材。于是农夫约翰到木材店购买木材。可是木材店老板说他这里只剩下少部分大规格的木板了。不过约翰可以购买这些木板,然后切割成他所需
要的规格。而且约翰有一把神奇的锯子,用它来锯木板,不会产生任何损失,也就是说长度为10的木板可以切成长
度为8和2的两个木板。你的任务:给你约翰所需要的木板的规格,还有木材店老板能够给出的木材的规格,求约翰
最多能够得到多少他所需要的木板。
Input
第一行为整数m(m<= 50)表示木材店老板可以提供多少块木材给约翰。紧跟着m行为老板提供的每一块木板的长度。接下来一行(即第m+2行)为整数n(n <= 1000),表示约翰需要多少木材。接下来n行表示他所需要的每一块木板
的长度。木材的规格小于32767。(对于店老板提供的和约翰需要的每块木板,你只能使用一次)。
Output
只有一行,为约翰最多能够得到的符合条件的木板的个数。Sample Input
430
40
50
25
10
15
16
17
18
19
20
21
25
24
30
Sample Output
7HINT
25切出 21 30切出 20 40切出 19、18 50切出 15、16、17思路:
首先,此题属于最小值最大化问题,果断下二分答案,而此题适用于left no AND right no BUT mid yes 的二分查找。
唔,据网上blogs,背包动归的写法还不如搜索+剪枝,所以此题约等于贪心题目,于是有了:
优化part 1:将店主可提供的木板和farmer John的需要木板进行排序。
那么,暴搜的框架就不再赘述,下面我们看看此题的剪枝。。。
可行性剪枝1:自然是搜完啦farmer John要买的最小mid个的木板后,向二分查找return 1咯。
可行性剪枝2:累计切割后剩下不能再用的木板,计为waste,处理要买的木板的前缀和,计为s[],并且滴,累积商店里所有木板的长度为sum(好吧,tot||total||cnt也行,但是sum s是更和谐的),当s[mid](当前要买的mid个木板总长)+waste>sum时,也就是搜索目标最小值所用最优木板长度比可承受长度还长,那么剪枝。
优化:当枚举的下一个要买到的木板长度和当前搞好的木板长度相同时,继续从当前商店的用过切过的木板i开始解决,否则从1开始。
此题大概就是如此吧,具体的那些难以言表东西交给我的代码解决吧!
二分答案技能get!
//最近get技能read()函数,陷入三目运算符中不能自拔(表示noip不能用啊)。
1592592
ksq2013 | 1082 | Accepted | 828 kb | 4 ms | C++/Edit | 1287 B | 2016-08-15 17:16:48 |
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int l,r,mid,ans=0; int n,m,c[51],b[51],a[1001],s[1001]={0},sum=0; int read() { int x=0,c=getchar(),f=1; while(c<48||c>57){if(c=='-')f=-1;c=getchar();} while(c>47&&c<58)x=x*10+c-48,c=getchar(); return x*f; } bool dfs(int last,int waste,int cur) { if(!cur)return 1; if(waste+s[mid]>sum)return 0; for(int i=last;i<=m;i++) if(c[i]>=a[cur]){ c[i]-=a[cur]; int tmp=c[i]<a[1]?c[i]:0; int nxt=a[cur]==a[cur-1]?i:1; if(dfs(nxt,waste+tmp,cur-1)) return 1; c[i]+=a[cur]; } return 0; } int main() { m=read(); for(int i=1;i<=m;i++) b[i]=read(),sum+=b[i]; n=read(); for(int i=1;i<=n;i++) a[i]=read(); sort(a+1,a+1+n); sort(b+1,b+1+m); for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i]; for(;s >sum;n--); l=0,r=n; while(l<=r){ mid=(l+r)>>1; memcpy(c,b,sizeof(b)); if(dfs(1,0,mid))ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); return 0; }
相关文章推荐
- bzoj1082[SCOI2005]栅栏
- BZOJ 1082 SCOI 2005 栅栏 搜索+剪枝
- [BZOJ1082][SCOI2005]栅栏
- bzoj1082: [SCOI2005]栅栏
- 【BZOJ1082】【SCOI2005】栅栏
- bzoj1082 [SCOI2005]栅栏
- 【BZOJ】1082: [SCOI2005]栅栏(二分+dfs)
- BZOJ 1082 [SCOI2005]栅栏 二分+DFS
- [bzoj] 1082: [SCOI2005]栅栏
- [BZOJ 1082] [SCOI2005] 栅栏 【二分 + DFS验证(有效剪枝)】
- BZOJ1082: [SCOI2005]栅栏 题解
- [BZOJ1082][SCOI2005]栅栏
- 【bzoj1082】[SCOI2005]栅栏
- 【BZOJ 1082】[SCOI2005]栅栏 二分+dfs
- bzoj 1082 [SCOI2005]栅栏 搜索姿势不对毁一生
- 【bzoj1082】[SCOI2005]栅栏
- BZOJ1082: [SCOI2005]栅栏
- bzoj 1082: [SCOI2005]栅栏 (二分+dfs)
- BZOJ1082 [SCOI2005]栅栏
- [bzoj1082][SCOI2005]栅栏(二分+dfs剪枝)