牛客网 网易2019实习生招聘编程题第八题 子集生成+二分

https://www.nowcoder.com/test/9763997/summary

牛牛准备参加学校组织的春游, 出发前牛牛准备往背包里装入一些零食, 牛牛的背包容量为w。
牛牛家里一共有n袋零食, 第i袋零食体积为v[i]。
牛牛想知道在总体积不超过背包容量的情况下,他一共有多少种零食放法(总体积为0也算一种放法)。
输入描述:
输入包括两行
第一行为两个正整数n和w(1 <= n <= 30, 1 <= w <= 2 * 10^9),表示零食的数量和背包的容量。
第二行n个正整数v[i](0 <= v[i] <= 10^9),表示每袋零食的体积。



输出描述:
输出一个正整数, 表示牛牛一共有多少种零食放法。
输入例子1:
3 10
1 2 4
输出例子1:
8
例子说明1:
三种零食总体积小于10,于是每种零食有放入和不放入两种情况,一共有2*2*2 = 8种情况。

解析 我们一半一半枚举 枚举前一半 把每种情况的体积和存到数组ans里 再枚举后一半 当枚举到一种情况的体积和为sum时 二分查找数组ans中值小于等于w-sum的数量 加到答案里

AC代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll mod=1000000007,maxn=5e4+50;
 5 vector<ll> a,ans;
 6 ll n,m;
 7 int main()
 8 {
 9     while(cin>>n>>m)
10     {
11         a.clear(),ans.clear();
12         for(int i=0; i<n; i++)
13         {
14             ll x;
15             cin>>x,a.push_back(x);
16         }
17         ll n1=n>>1,n2=n-n1;
18         for(int i=0; i<(1<<n1); i++)
19         {
20             ll sum=0;
21             for(int j=0; j<n1; j++)
22                 if(i&(1<<j)) sum+=a[j];
23             ans.push_back(sum);
24         }
25         sort(ans.begin(),ans.end());
26         ll anss=0;
27         for(int i=0; i<(1<<n2); i++)
28         {
29             ll sum=0;
30             for(int j=0; j<n2; j++)
31             {
32                 if(i&(1<<j))
33                     sum+=a[n1+j];
34             }
35             anss+=lower_bound(ans.begin(),ans.end(),m-sum+1)-ans.begin();
36         }
37         cout<<anss<<endl;
38     }
39 }

猜你喜欢

转载自www.cnblogs.com/stranger-/p/9069405.html