Solution
有一个贪心策略——尽量满足较小的需要的木板
于是可以先将需要的木板从小到大排序,二分出最多能满足前多少块木板
有减小二分区间的策略——提供的木块总长度必须 >= 所有要满足的木板的总长度
如何check呢?
考虑暴力思想——搜索,按需要满足的木板顺序搜索
但肯定需要剪枝
剪枝1:提供的木块总长度-当前已舍弃的长度 > = 所有要满足的木板的总长度
剪枝2:及时舍弃不能满足任何木板的 提供的木板
Code
#include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; const int M=51,N=1001; int a[M],b[N],n,m,tot,ma,t,sum,s[N],fa[M]; bool dfs(int k,int x,int mid) { if(k<=0) return 1; if(sum-t<s[mid]) return 0; for(int i=x;i<=m;i++) if(fa[i]>=b[k]) { fa[i]-=b[k]; if(fa[i]<b[1]) t+=fa[i]; if(b[k]==b[k-1]) { if(dfs(k-1,i,mid)) return 1; } else if(dfs(k-1,1,mid)) return 1; if(fa[i]<b[1]) t-=fa[i]; fa[i]+=b[k]; } return 0; } int main() { scanf("%d",&m); for(int i=1;i<=m;i++) scanf("%d",&a[i]),ma=max(ma,a[i]); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&b[++tot]); if(b[tot]>ma) tot--; } n=tot,tot=0; sort(b+1,b+1+n); for(int i=1;i<=m;i++) if(a[i]>=b[1]) a[++tot]=a[i]; m=tot; sort(a+1,a+1+m); for(int i=1;i<=m;i++) sum+=a[i]; for(int i=1;i<=n;i++) s[i]=s[i-1]+b[i]; while(sum<s[n]) n--; int l=0,r=n; while(l<r) { t=0; for(int i=1;i<=m;i++) fa[i]=a[i]; int mid=(l+r+1)>>1; if(dfs(mid,1,mid)) l=mid; else r=mid-1; } printf("%d\n",l); return 0; }
来源:https://www.cnblogs.com/hsez-cyx/p/12446614.html