Wannafly挑战赛6 D-锁 思维

本文介绍了Wannafly挑战赛中的D-锁问题,涉及ACM竞赛。题目要求确定最少数量的锁,使得重要度总和小于m的居民无法开启门,而重要度总和大于等于m的居民可以。通过分析临界组合和使用动态规划进行状态转移,可以解决这一问题。样例解释和正确性分析有助于理解解题思路。
摘要由CSDN通过智能技术生成

题目链接:
https://www.nowcoder.com/acm/contest/37/D
Description

106号房间共有n名居民, 他们每人有一个重要度。房间的门上可以装若干把锁。假设共有k把锁,命名为1到k。每把锁有一种对应的钥匙,也用1到k表示。钥匙可以复制并发给任意多个居民。每个106房间的居民持有若干钥匙,也就是1到k的一个子集。如果几名居民的钥匙的并集是1到k,即他们拥有全部锁的对应钥匙,他们都在场时就能打开房门。新的陆战协定规定,一组居民都在场时能打开房门当且仅当他们的重要度加起来至少为m。问至少需要给106号房间装多少把锁。即,求最小的k,使得可以适当地给居民们每人若干钥匙(即一个1到k的子集),使得任意重要度之和小于m的居民集合持有的钥匙的并集不是1到k,而任意重要度之和大于等于m的居民集合持有的钥匙的并集是1到k。

Input

第一行两个整数n和m,0 < n<21,0 < m<1000000001。
第二行n个整数表示居民们的重要度。
重要度在[1,1000000000]之间。

Output

一个整数表示最少需要多少把锁。

Example

输入
4 3
1 1 1 1
输出
6
说明
106号房共有4名居民,只有3人在场时才能打开门。这时共需6把锁。

题意
- 先解释一下样例为什么是6,如果有6把锁,那么居民1拿【1,2,3】,居民2拿【3,4,5】,居民3拿【1,2,5】,居民4拿【4,5,6】,可以验证任意两个人都加起来都凑不齐1-6所有的钥匙,但任意三个人都加起来都可以凑齐1-6所有的钥匙。
分析
-定义临界组合:重要度刚好不够的组合。即这个组合里的人重要度不足m,但加上组合外任意一个人的重要度,和就大于等于m的组合。
- 注意到n<21,很容易想到这个范围刚好可以状压,就可以处理重要度临界的问题。我们分析这个题目所要求的条件,要求重要度不足m的不能开门,超过m的一定能开门,这是一个很重要的临界条件,为了减小锁的数量,我们就让【临界组合】刚好缺一把钥匙。
- 正确性分析:每种这样的组合缺的钥匙必须不一样的,因为如果组合1,组合2都缺钥匙K,那么把组合1和组合2并起来,重要度大于了m,却还是缺钥匙K。所以我们要保证每一个临界组合的缺的钥匙不同,换言之,题中求最少需要几把钥匙,就是统计临界组合的个数。

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int a[25];
int main()
{
    int n,M,ans = 0;
    scanf("%d%d",&n,&M);
    for(int i = 0;i < n;i++) scanf("%d",&a[i]);
    for(int i = 0;i < (1<<n);i++){
        LL m = 0;
        for(int j = 0;j < n;j++)
            if(i & (1<<j)) m += a[j];
        if(m >= M) continue;
        int flag = 1;
        for(int j = 0;j < n;j++)
            if((i&(1<<j)) == 0 && m+a[j]<M) flag = 0;
        ans += flag;
    }
    printf("%d\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值