NC14732 锁
题意:
n个居民,门上有k把锁,每个居民有若干钥匙,为1到k的一个子集,如果几名居民的钥匙的并集是1到k,即他们拥有全部锁的对应钥匙。
求最小的k,使得可以适当地给居民们每人若干钥匙(即一个1到k的子集),使得任意重要度之和小于m的居民集合持有的钥匙的并集不是1到k,而任意重要度之和大于等于m的居民集合持有的钥匙的并集是1到k
题解:
思路很妙
很明显是状压
我的思路一开始都跑偏了,我想的是枚举每个人拥有的钥匙状态,但是钥匙的数量是未知的
我们这样想:
重要度不足m的不能开门,大于m的一定能开门,对于一个状态i,i表示包含一些人但是重要度不足m的状态,当再加入任意一个人x后,就会超过m,说明x含有的钥匙是状态i没有的,所以问题就是求有多少个这样的状态i
对于当前状态(小于m),判断是否对于每个人而言加上他都是可以大于m,如果可以就算一个答案,只要存在一个人加上他也不满足,那此状态作废
这个讲得透彻
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[30];
ll ans=0;
ll n,m;int main ()
{scanf("%lld%lld",&n,&m);for(int i=0;i<n;i++) scanf("%lld",&a[i]);for(int i=0;i<(1<<n);i++){ll lo=0;for(int j=0;j<n;j++) if(i&(1<<j)) lo+=a[j];if(lo>=m) continue;bool flag=true;for(int j=0;j<n;j++) if(!(i&(1<<j)))//当前状态没有第j个人 if(lo+a[j]<m) flag=false;if(flag) ans++;}printf("%lld\n",ans);
}