[jzoj 1284] 病毒 {状态压缩dp}

版权声明:~~~感谢支持! https://blog.csdn.net/qq_39897867/article/details/88599579

题目

Description

D(1<=D<=15)种病毒正袭击着牧场里的奶牛,这给牧场主约翰造成了极大的麻烦,因为按照卫生检疫条例的规定:如果牛奶中的病毒超过K(1<=K<=D)种则不允许被销售,约翰的牧场里共有N(1<=N<=1,000)头奶牛,每头奶牛都带有若干种病毒,约翰挤出的牛奶是混放在一起的,要求约翰最多可以挤多少头奶牛的牛奶,使得混放在一起的牛奶不包含超过K种的病毒。

Input

输入文件的第一行有三个用空格隔开的整数N,D,K,接下来的N行每行表示一头奶牛的病毒列表,每行的第一个数d_i(0<=d_i<=D)表示该头奶牛共携带了d_i种病毒,紧接着的d_i个整数表示该头奶牛共携带的每一种病毒的编号,相邻两数之间用空格隔开。

Output

输出文件仅有一行包含一个整数,表示约翰最多可以挤多少头奶牛的牛奶,使得混放在一起的牛奶不包含超过K种的病毒。


解题思路

a [ i ] [ j ] i j 设a[i][j]表示前i头牛病毒状态为j的最优解。
{\color{Orange}*可以用滚动数组*}

a [ c 1 ] [ j ] = m a x ( a [ c 1 ] [ j ] , a [ c ] [ j ] ) ; a [ c 1 ] [ j b [ i ] ] = m a x ( a [ c 1 ] [ j b [ i ] ] , a [ c ] [ j ] + 1 ) ; {\color{Orange}} a[c\oplus1][j]=max(a[c\oplus 1][j],a[c][j]); \\ a[c\oplus1][j|b[i]]=max(a[c\oplus 1][j|b[i]],a[c][j]+1);


代码

#include<cstdio>
#include<algorithm>
#include<string>
#define rep(i,x,y) for (register int i=x;i<=y;i++)
using namespace std;
int n,d,k,a[2][340000],b[100005],ans,c,tot; bool t[100005];  
int main(){
	scanf("%d%d%d",&n,&d,&k);
	int x,y; 
	rep(i,1,(1<<d)-1) {
		tot=0; x=i; while(x) { if (x&1) tot++; x>>=1;}
    	t[i]=(tot<=k)?1:0; 
	}
	rep(i,1,n) {
		scanf("%d",&x); 
		rep(j,1,x) scanf("%d",&y),b[i]|=(1<<y-1); 
	}
	rep(i,1,n){
		rep(j,0,(1<<d)-1) a[c^1][j]=-2147483247; 
		rep(j,0,(1<<d)-1) {
			a[c^1][j]=max(a[c^1][j],a[c][j]); 
			a[c^1][j|b[i]]=max(a[c^1][j|b[i]],a[c][j]+1); 
			if (t[j]) ans=max(ans,a[c][j]); 
		}		
		c^=1; 
	}
	rep(i,0,(1<<d)-1) if (t[i]) ans=max(ans,a[c][i]); 
	printf("%d",ans); 
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/88599579