当前位置: 代码迷 >> 综合 >> AcWing 1243. 糖果 状态dp
  详细解决方案

AcWing 1243. 糖果 状态dp

热度:7   发布时间:2023-11-23 13:43:51.0

AcWing 1243. 糖果

糖果店的老板一共有 M 种口味的糖果出售。

为了方便描述,我们将 M 种口味编号 1?M。

小明希望能品尝到所有口味的糖果。

遗憾的是老板并不单独出售糖果,而是 K 颗一包整包出售。

幸好糖果包装上注明了其中 K 颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。

给定 N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。

输入格式
第一行包含三个整数 N,M,K。

接下来 N 行每行 K 这整数 T1,T2,???,TK,代表一包糖果的口味。

输出格式
一个整数表示答案。

如果小明无法品尝所有口味,输出 ?1。

数据范围
1≤N≤100,
1≤M,K≤20,
1≤Ti≤M
输入样例:

6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2

输出样例:

2

这道题其实y总是用了一个lowbit的方法去做的(没看懂),然后看题解了解到一个状态dp,然后我去做了一下试试,状态dp 的思想也比较简单。

d p [ i , j ] = m i n ( d p [ i ? 1 , j ] , d p [ i ? 1 , j ( w [ i ] ) ] + 1 ) dp[i,j]=min(dp[i-1,j],dp[i-1,j(~w[i])]+1) dp[i,j]=min(dp[i?1,j],dp[i?1,j( w[i])]+1)

dp[i,j],是遍历前i种形成j状态的最小方案数。

然后状态表达和状态计算给出来之后,开始写代码。

代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;const int N=110,M=1<<20;int dp[M],wi[N];
int n, m ,k;int main(void)
{
    cin>>n>>m>>k;for(int i=1;i<=n;i++){
    for(int j=1;j<=k;j++){
    int t;cin>>t;wi[i]|=(1<<t-1);}}memset(dp,0x3f,sizeof dp);//设无穷大表示不存在dp[0]=0;for(int i=1;i<=n;i++)for(int j=0;j<(1<<m);j++)dp[j]=min(dp[j],dp[j&(~wi[i])]+1);if(dp[(1<<m)-1]==0x3f3f3f3f)puts("-1");elsecout<<dp[(1<<m)-1];
}