2019-I(糖果)
状态压缩动态规划
#include <bits/stdc++.h> //动态规划,用二进制表示每一位的状态 using namespace std; #define MAXN 105 int N,K,M,tmp; //f的大小为所有状态的总个数 int f[1<<20],a[MAXN]; //f[S]表示为达成S集合所需要的最少糖果袋数,初始值设为正无穷(127,只要大与MAXN即可),f[0] = 0 int main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); cin>>N>>M>>K; for(int i=0;i<N;i++){//统计每袋糖果的种类 for(int j=0;j<K;j++){ cin>>tmp; a[i] |= 1<<(tmp-1);//用或运算表示两个集合的合并 //注意表示的意思是1左移tmp-1为位置 } } memset(f,127,sizeof(f));//将f的值全部设置为127 f[0] = 0; for(int i=0;i<N;i++){//对每一袋依次进行枚举 for(int S=0;S<(1<<M);S++){//枚举糖果所有可能的组合状态,从0到2的M次方减1 if(f[S] > MAXN) continue;// 说明当前的糖果状态还不能达到 //由当前可达到的状态生成一种新的状态 f[S|a[i]] = min(f[S|a[i]],f[S]+1);//取之前那个状态和有当前状态+a[i]转化过去的最小值 } } cout << (f[(1 << M) - 1] < MAXN ? f[(1 << M) - 1] : -1) << endl; return 0; }