注释很详细
#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; }