「BZOJ1082」[SCOI2005] 栅栏
Description
农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材。于是农夫约翰到木材店购买木材。可是木材店老板说他这里只剩下少部分大规格的木板了。不过约翰可以购买这些木板,然后切割成他所需要的规格。而且约翰有一把神奇的锯子,用它来锯木板,不会产生任何损失,也就是说长度为10的木板可以切成长度为8和2的两个木板。你的任务:给你约翰所需要的木板的规格,还有木材店老板能够给出的木材的规格,求约翰最多能够得到多少他所需要的木板。
Input
第一行为整数m(m<= 50)表示木材店老板可以提供多少块木材给约翰。紧跟着m行为老板提供的每一块木板的长度。接下来一行(即第m+2行)为整数n(n <= 1000),表示约翰需要多少木材。接下来n行表示他所需要的每一块木板的长度。木材的规格小于32767。(对于店老板提供的和约翰需要的每块木板,你只能使用一次)。
Output
只有一行,为约翰最多能够得到的符合条件的木板的个数。
Sample Input
4
30
40
50
25
10
15
16
17
18
19
20
21
25
24
30
30
40
50
25
10
15
16
17
18
19
20
21
25
24
30
Sample Output
7
HINT
25切出 21 30切出 20 40切出 19、18 50切出 15、16、17
题解
二分搜索+剪枝
将木板排序,二分可以切出木板的数量
当然是切最小的mid块
然后从大到小搜索每块木板用哪个木材切
剪枝就是当木材大小小于最小的木块则丢弃
记录当前丢弃的木材量,若加上mid块木板 > 所有的木材 则不合法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
#include<cstdio> #include<cmath> #include<ctime> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #include<set> #define ll long long #define inf 1000000000 using namespace std; int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } bool flag; int n,m,mid; int a[55],b[1005],bl[1005]; ll sa; int sb[1005]; void dfs(int ak,int bk,int w) { if(bk==0)flag=1; while(ak<=n&&a[ak]<b[1]){w+=a[ak];ak++;} if(flag||ak>n)return; if(w+sb[mid]>sa)return; int t=ak,t1=ak,t2=bk,t3=w; if(b[bk]==b[bk+1]&&bk!=mid)t=bl[bk+1]; for(int i=t;i<=n;i++) if(a[i]>=b[bk]) { bl[bk]=i;a[i]-=b[bk]; bk--; dfs(ak,bk,w); ak=t1;bk=t2;w=t3;a[i]+=b[t2]; } } int main() { n=read(); for(int i=1;i<=n;i++)a[i]=read(); m=read(); for(int i=1;i<=m;i++)b[i]=read(); sort(a+1,a+n+1); sort(b+1,b+m+1); while(b[m]>a[n])m--; int tot=0; for(int i=1;i<=n;i++) if(a[i]>b[1])a[++tot]=a[i]; n=tot; for(int i=1;i<=n;i++)sa+=a[i]; for(int i=1;i<=m;i++)sb[i]=sb[i-1]+b[i]; int l=1,r=m,ans=0; while(l<=r) { mid=(l+r)>>1; flag=0;dfs(1,mid,0); if(flag)ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); return 0; } |
Subscribe