状压dp例题,| 二进制取反, > 二进制左移,学到了
写出来状态方程就行了
```cpp
#include<bits/stdc++.h>
using namespace std;
#define ll long long
using namespace std;
const int maxn=(1<<21);
int dp[maxn],candy[1000];
int main(){
int n,m,k;
int i,j;
int a;
//dp[i]表示在i这种状态下最少的糖的包数;
cin>>n>>m>>k;
for(i=0;i<n;i++){
for(j=0;j<k;j++){
cin>>a;
candy[i]|=1<<(a-1);
}
cout << candy[i] << endl;
dp[candy[i]]=1;//此状态加入了要多加一包糖
}
for(i=0;i<n;i++){
for(j=1;j<=(1<<m);j++){
if(dp[j]==0) continue;//如果这种状态在先前不存在,是不能转移的
if(dp[j|candy[i]]==0||dp[j|candy[i]]>dp[j]+1){
dp[j|candy[i]]=dp[j]+1;
/*
/*至少需要dp[j]包糖果,我再加上此时的第i包糖果,新的状态可能不存在,那么
这个新的状态就需要dp[j]+1包糖果;如果加上此时的第i包糖果,新的状态存在
了,那就得比较比较所需的糖果谁的少,取少的。*/
}
}
}
if(dp[(1<<m)-1]!=0){
cout<<dp[(1<<m)-1]<<endl;
}
else{
cout<<-1<<endl;
}
return 0;
}