题目链接:糖果
解题思路:状态压缩+动态规划,用二进制存储每个糖果是否买到过(1表示买到,0表示没买),20种糖果都买到的只有
(
1
<
<
20
)
−
1
(1<<20)-1
( 1 < < 2 0 ) − 1 ,给每一个数的状态都初始化标记,给每一袋糖果的种类都存在二进制里就会是一个数,这个数的二进制就表示这袋糖果有哪些种类。枚举每一袋糖果,买当前这袋与哪些已经买到过的状态的糖果转移过去。
#include <bits/stdc++.h>
#define x first
#define y second
#define mem1(h) memset(h,-1,sizeof h)
#define mem0(h) memset(h,0,sizeof h)
#define mcp(a,b) memcpy(a,b,sizeof b)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair< int , int > PII;
typedef pair< double , double > PDD;
namespace IO{
inline LL read ( ) {
LL o= 0 , f= 1 ; char c= getchar ( ) ;
while ( c< '0' || c> '9' ) { if ( c== '-' ) f= - 1 ; c= getchar ( ) ; }
while ( c>= '0' && c<= '9' ) { o= o* 10 + c- '0' ; c= getchar ( ) ; }
return o* f;
}
} using namespace IO;
const int N= 1e2 + 7 , M= 2e5 + 7 , INF= 0x3f3f3f3f , mod= 1e9 + 7 , P= 131 ;
int f[ 1 << 20 ] ;
int s[ N] ;
int n, m, k;
int main ( ) {
scanf ( "%d%d%d" , & n, & m, & k) ;
int all= ( 1 << m) - 1 ;
for ( int i= 0 ; i<= all; i++ ) f[ i] = INF;
for ( int i= 0 ; i< n; i++ ) {
int state= 0 ;
for ( int j= 0 ; j< k; j++ ) {
int candy;
scanf ( "%d" , & candy) ;
candy-- ;
state| = 1 << candy;
}
s[ i] = state;
f[ state] = 1 ;
}
for ( int i= 0 ; i< n; i++ ) {
for ( int j= 0 ; j<= all; j++ ) {
if ( f[ j] == INF) continue ;
f[ j| s[ i] ] = min ( f[ j| s[ i] ] , f[ j] + 1 ) ;
}
}
if ( f[ all] == INF) cout<< - 1 << endl;
else cout<< f[ all] << endl;
return 0 ;
}