AcWing 1243. 糖果(状压DP)

题目描述

糖果店的老板一共有 MM 种口味的糖果出售。
为了方便描述,我们将 MM 种口味编号 1∼M1∼M。
小明希望能品尝到所有口味的糖果。
遗憾的是老板并不单独出售糖果,而是 KK 颗一包整包出售。
幸好糖果包装上注明了其中 KK 颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。
给定 NN 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。

输入格式

第一行包含三个整数 N,M,KN,M,K。
接下来 NN 行每行 KK 这整数 T1,T2,⋅⋅⋅,TKT1,T2,···,TK,代表一包糖果的口味。

输出格式

一个整数表示答案。
如果小明无法品尝所有口味,输出 −1−1。

数据范围

1≤N≤1001≤N≤100,
1≤M,K≤201≤M,K≤20,
1≤Ti≤M


题解:
数据范围很小,又是求最优解,很明显的状压DP

但是直接这样写肯定会爆内存,那么我们可以根据它只和前一次处理的结果有关,于是滚动优化一下内存就过了


AC代码:

扫描二维码关注公众号,回复: 8690194 查看本文章
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
const int MAXN = (1<<20)+5;
const int MOD = 100003;
const int INF = 0x3f3f3f3f;
int dp[2][MAXN],sta[105];
int n,m,k;
inline void Init(){
    for(int i=0;i<2;i++)
        for(int j=0;j<(1<<m);j++)
            dp[i][j]=1e9;
}
signed main(){
#ifndef ONLINE_JUDGE
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
    scanf("%d%d%d",&n,&m,&k); Init();
    for(int i=1;i<=n;i++) for(int j=0,x;j<k;j++) scanf("%d",&x),sta[i]|=(1<<(x-1));
    dp[0][0]=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<(1<<m);j++){
       		if(dp[(i+1)&1][j]>=1e9) continue;
            dp[i&1][j|sta[i]] = min(dp[i&1][j|sta[i]],dp[(i+1)&1][j]+1);
            dp[i&1][j] = min(dp[i&1][j],dp[(i+1)&1][j]);
        }
    }
    if(dp[n&1][(1<<m)-1]>=1e9) puts("-1");
    else printf("%d\n",dp[n&1][(1<<m)-1]);
    return 0;
}

发布了152 篇原创文章 · 获赞 1 · 访问量 2714

猜你喜欢

转载自blog.csdn.net/qq_43544481/article/details/103773884