nyoj167
题意:
小珂有一个奶牛场,奶牛场最近在流行D(1<D<=15)种病毒,小珂的农场一共有N(1<N<=1000)只奶牛,含超过K(1<=K<=D)种病毒的牛奶不得不丢弃.(牛奶中含有奶牛身上的病毒)。现在希望你写一个程序,来确定一下一个桶里的最多可以包含多少头奶牛的牛奶。
思路:
状压,然后每次枚举补集,dp。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n,d,k;
int dp[1<<15];
bool Judge(int x)
{
int num = 0;
while(x)
{
int t = x%2;
if(t) num++;
if(num > k) return false;
x>>=1;
}
return true;
}
int main()
{
int T,W,cur,x,i,num,j;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&d,&k);
memset(dp,0,sizeof(dp));
W = (1<<d) - 1;
for(i = 0; i < n; i++)
{
scanf("%d",&num);
cur = 0;
while(num--)
{
scanf("%d",&x);
cur |= (1<<(x-1));
}
dp[cur] += 1;
int temp = W ^ cur;
for(j=temp; j; j = (j-1)&temp)
dp[j|cur]=dp[j|cur] + 1;
}
int ans = 0;
for(i=0; i<=W; i++)
if(Judge(i))
ans=max(ans,dp[i]);
printf("%d\n",ans);
}
return 0;
}
zoj3305
题意:
有n(<=16)种原料,编号1-n,m(<=50000)种配方,现在要在每种原料最多用一次的情况下,配出最多的配方。
思路:
状压,然后每次枚举补集,dp。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n,m,W;
int dp[1<<16];
int main(){
int k,x,cur,pre,ans;
while(~scanf("%d%d",&n,&m)){
W=(1<<n)-1;
memset(dp,0,sizeof(dp));
for(int i=1;i<=m;i++){
scanf("%d",&k);
cur = 0;
while(k--)
{
scanf("%d",&x);
cur |= (1<<(x-1));
}
dp[cur] = max(dp[cur],1);
pre = W ^ cur;
/*******这样枚举跑的还很快?************/
for(int j=pre;j;j=(j-1)&pre)
if(dp[j]) dp[cur|j] = max(dp[cur|j],dp[j]+1);
/*******************/
}
ans = 0;
for(int i=1;i<=(1<<n)-1;i++)
ans = max(ans, dp[i]);
printf("%d\n",ans);
}
return 0;
}