[bzoj1082]栅栏

先二分答案,然后搜索暴力判断
由于数据范围较大,需要剪枝:1.当前所有可能被用到的木板长度和(长度要不小于最小所需长度)>=所要拼成的所有木板的和;2.对于需求从大到小枚举木板(这样一开始枚举次数较少,后来的情况容易被剪枝掉)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,a[105],b[1005];
 4 bool dfs(int k,int s){
 5     if (s<0)return 0;
 6     if (!k)return 1;
 7     for(int i=1;i<=n;i++)
 8         if (a[i]>=b[k]){
 9             a[i]-=b[k];
10             if (dfs(k-1,s-a[i]*(a[i]<b[1]))){
11                 a[i]+=b[k];
12                 return 1;
13             }
14             a[i]+=b[k];
15         }
16     return 0;
17 }
18 int main(){
19     scanf("%d",&n);
20     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
21     scanf("%d",&m);
22     for(int i=1;i<=m;i++)scanf("%d",&b[i]);
23     sort(a+1,a+n+1);
24     sort(b+1,b+m+1);
25     int l=0,r=m;
26     while (l<r){
27         int mid=(l+r+1>>1),s=0;
28         for(int i=1;i<=n;i++)s+=a[i];
29         for(int i=1;a[i]<b[1];i++)s-=a[i];
30         for(int i=1;i<=mid;i++)s-=b[i];
31         if (dfs(mid,s))l=mid;
32         else r=mid-1;
33     }
34     printf("%d",l);
35 }
View Code

 

posted @ 2019-11-05 08:10  PYWBKTDA  阅读(180)  评论(0编辑  收藏  举报