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