农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材。于是农夫约翰到木材店购
买木材。可是木材店老板说他这里只剩下少部分大规格的木板了。不过约翰可以购买这些木板,然后切割成他所需
要的规格。而且约翰有一把神奇的锯子,用它来锯木板,不会产生任何损失,也就是说长度为10的木板可以切成长
度为8和2的两个木板。你的任务:给你约翰所需要的木板的规格,还有木材店老板能够给出的木材的规格,求约翰
最多能够得到多少他所需要的木板。
标签:
农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材。于是农夫约翰到木材店购
买木材。可是木材店老板说他这里只剩下少部分大规格的木板了。不过约翰可以购买这些木板,然后切割成他所需
要的规格。而且约翰有一把神奇的锯子,用它来锯木板,不会产生任何损失,也就是说长度为10的木板可以切成长
度为8和2的两个木板。你的任务:给你约翰所需要的木板的规格,还有木材店老板能够给出的木材的规格,求约翰
最多能够得到多少他所需要的木板。
第一行为整数m(m<= 50)表示木材店老板可以提供多少块木材给约翰。紧跟着m行为老板提供的每一块木板的长
度。接下来一行(即第m+2行)为整数n(n <= 1000),表示约翰需要多少木材。接下来n行表示他所需要的每一块木板
的长度。木材的规格小于32767。(对于店老板提供的和约翰需要的每块木板,你只能使用一次)。
只有一行,为约翰最多能够得到的符合条件的木板的个数。
25切出 21 30切出 20 40切出 19、18 50切出 15、16、17
正解:二分答案+搜索
解题报告:
今天考试T2。
考场上面写的是二分+贪心,然而我自己也拍出错来了。但是因为姿势比较正确,拿到了70分。可以证明这道题没有办法贪心,只能选择搜索。当然,即便是搜索,也许要用到二分。然而m<=1000的数据范围简直让人绝望啊...我们只能想办法剪枝,有一些剪枝很清楚:排序,去掉无用的。这题还有一些剪枝:如果某个盆子已经装不下任何一个(就是最小的都装不下了)可以记录一下浪费了多少空间,然后加起来,如果超过了总容量与当前二分值的差,那么一定无法放完。还有就是如果下一个星星的体积与当前相同(即完全相同),那么可以发现没必要从1开始重新扫一遍,因为当前用到i就说明之前的已经放不下了,所以可以记录一下循环开始的位置,从而减少迭代。这样的话就可以过掉USACO还有SCOI的所有数据了。
1 //It is made by jump~ 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <ctime> 9 #include <vector> 10 #include <queue> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long LL; 15 const int inf = (1<<30); 16 const int MAXN = 60; 17 const int MAXM = 1030; 18 int n,m,cnt,l,r; 19 int a[MAXN],star[MAXM],c[MAXM],sum[MAXM]; 20 int ans,rest,tot,now; 21 22 inline int getint() 23 { 24 int w=0,q=0; char c=getchar(); 25 while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar(); if(c==‘-‘) q=1,c=getchar(); 26 while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar(); return q ? -w : w; 27 } 28 29 inline bool dfs(int x,int from){ 30 if(x==0) return true; 31 if(now>rest) return false; 32 for(int i=from;i<=n;i++) { 33 if(a[i]<star[x]) continue; 34 a[i]-=star[x]; 35 if(a[i]<star[1]) now+=a[i];//i没有任何作用了,加入剩余的中,进入剪枝 36 if(star[x]==star[x-1]) { if(dfs(x-1,i))return true;}//直接从这一位开始,因为已经扫描到i说明之前的已经无用了 37 else if(dfs(x-1,1)) return true; 38 if(a[i]<star[1]) now-=a[i]; 39 a[i]+=star[x]; 40 } 41 return false; 42 } 43 44 inline void work(){ 45 n=getint(); for(int i=1;i<=n;i++) c[i]=a[i]=getint(),tot+=a[i]; 46 m=getint(); for(int i=1;i<=m;i++) star[i]=getint(); 47 sort(a+1,a+n+1); sort(c+1,c+n+1); sort(star+1,star+m+1); 48 for(int i=1;i<=m;i++) sum[i]=sum[i-1]+star[i]; 49 int mid; l=0; while(sum[m]>tot) m--;//去掉没有意义的 50 r=m; 51 while(l<=r) { 52 mid=(l+r)/2; now=0; rest=tot-sum[mid];//剩余的 53 if(dfs(mid,1)) l=mid+1,ans=mid; 54 else r=mid-1; 55 for(int i=1;i<=n;i++) a[i]=c[i]; 56 } 57 printf("%d",ans); 58 } 59 60 int main() 61 { 62 work(); 63 return 0; 64 }
标签:
原文地址:http://www.cnblogs.com/ljh2000-jump/p/5924770.html