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