World finals 2005的题,挺容易的。
如何计算重复的,画个图就知道了。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<iterator>
#include<queue>
#include<ctime>
#include<bitset>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
//#define ll __int64
#define ll long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
struct node
{
int state;
int area;
}com[30];
int c;
int n,m,k;
int p[30];
int tzf[30];
int main()
{
int ca=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(!n&&!m) break;
for(int i=1;i<=n;i++)
{
scanf("%d",&p[i]);
}
scanf("%d",&c);
for(int i=1;i<=c;i++)
{
com[i].state=0;
scanf("%d",&k);
for(int j=0;j<k;j++)
{
scanf("%d",&tzf[j]);
com[i].state+=(1<<(tzf[j]-1));
}
scanf("%d",&com[i].area);
}
int top=(1<<n);
int ht;
int lim;
int ans_num=0;
int ans_state=0;
for(int i=0;i<top;i++)
{
int s=0;
int t1=i;
int nid=1;
lim=0;
while(t1)
{
if(t1&1) {lim++;s+=p[nid];}
nid++;
t1>>=1;
}
if(lim!=m) continue;
t1=i;
for(int j=1;j<=c;j++)
{
int t2=com[j].state;
t1=i;
ht=0;
nid=1;
while(t1&&t2)
{
if((t1&t2)&1) ht++;
t1>>=1;t2>>=1;
}
if(ht>=2)
{
s-=com[j].area*(ht-1);
}
}
if(s>ans_num)
{
ans_num=s;
ans_state=i;
}
}
printf("Case Number %d\n",ca++);
printf("Number of Customers: %d\n",ans_num);
printf("Locations recommended:");
int nid=1;
while(ans_state)
{
if(ans_state&1) printf(" %d",nid);
nid++;
ans_state>>=1;
}
puts("");
puts("");
}
return 0;
}