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;
}

 

posted @ 2021-03-06 20:20  zmachine  阅读(60)  评论(0编辑  收藏  举报