uva 11088 暴力枚举子集/状压dp

时间:2023-03-08 19:56:06
uva  11088  暴力枚举子集/状压dp

https://vjudge.net/problem/UVA-11088

对于每一种子集的情况暴力枚举最后一个三人小组取最大的一种情况即可,我提前把三个人的子集情况给筛出来了。 即 f[S]=MAX{ f[S^X]+ok(X) |  X€三个人的子集 } ok(X)判断X所有的和是否>=20;

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
int f[(<<)+];
vector<int>thr;
int total(int x)
{
int s=;
while(x){
if(x&) s++;
x>>=;
}
return s;
}
void init()
{
int all=(<<);
for(int i=;i<all;++i)
if(total(i)==) thr.push_back(i);
}
int a[];
bool can(int x)
{
int s=;
for(int j=;j<;++j)
if(x&(<<j)) s+=a[j+];
return s>=;
}
int main()
{
int N=,M,i,j,k=,t;
init();
while(cin>>N&&N){
for(i=;i<=N;++i) cin>>a[i];
memset(f,,sizeof(f));
int all=(<<N);
for(i=;i<all;++i)
{
for(j=;j<thr.size()&&i>=thr[j];++j)
{
if((i&thr[j])==thr[j]){
f[i]=max(f[i],f[i^thr[j]]+can(thr[j]));
}
}
}
printf("Case %d: %d\n",++k,f[all-]);
}
return ;
}