uva 1047 - Zones-World finals 2005 状态压缩枚举

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TommyTT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值