注释很详细
#include <bits/stdc++.h>
#define FIO ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long int ll;
ll n, m, impo[30];
int main() {
FIO;
cin>>n>>m;
for(int i = 1; i <= n; i++){
cin>>impo[i];
}
ll ans = 0;//初始的钥匙数为0
for(int i = 0; i < (1 << n); i++){
//从0遍历到2^n-1
//从二进制来看,就是从000...0(n个)遍历到111...1(n个)
//我们把1视作这个人在场,0视作这个人不在场
ll cur_sum = 0;//记录在场的人的重要度之和
ll min_impo = 999999999999;//记录所有不到场的人中重要度的最小值
for(int j = 0; j < n; j++){
if((1 << j) & i){
//1 << j的二进制是只有第j+1位为1,其余都为0,
// 只有i的2进制第j+1位为1, 这个值才可能为true
cur_sum += impo[j + 1];
}else{
//i的二进制的第j+1位为0
min_impo = min(min_impo, impo[j + 1]);
}
}
if(cur_sum >= m){
//已经到场的人的重要性已达标,一定可以打开门,直接跳过
continue;
}else{
//已经到场的人的重要性不达标
if(cur_sum + min_impo >= m){
//再来一个人,重要性一定就达标了,就一定可以打开房门
//就说明未在场的人都拥有至少一把在场的人都没有的钥匙
//那么就给未在场的人每人一把新钥匙,钥匙数+1
ans++;
//而且因为每次遍历,在场的人都不一样,就保证了每次都必须给一把新钥匙才能满足题意
}
}
}
cout<<ans<<endl;
return 0;
} 
京公网安备 11010502036488号