概率+状压+容斥原理(HDU 4336 Card Collector)详细讲解

在你的童年有过收集零食里面的卡片的经历吧!当你集得所有卡片的时候你会获得很多奖励。

输入的第一行代表需要集得卡片的数量NN,接下来的一行有N个实数,代表每张卡片出现的概率,问最少需要买多少零食才可以集全所有卡片。

输入n,代表所需卡片

接着输入n个数pi,代表每包零食中有这种卡片的个数

/*
先输入,接着处理;
处理过程:
每个卡片有买与不买两个状态,0代表不买,1代表买
给定n张卡片,故状态共有2^n方个状态,记为msk。
枚举每一个状态,即第一层循环,接着枚举每一个给定的零食j从1...n;
如果(msk&1<<j)不为0,代表这个状态用了这个零食,flag++;sum+=a[i];flag为该状态利用的零食个数
判断flag若是奇数,则累加,若是偶数则减;奇加偶减定理;
最后得到的就是所需卡片数;
*/
#include<bits/stdc++.h>
using namespace std;
double a[25];
void solve(int N)
{
    double ans=0.0;
    for(int msk=1; msk<(1<<N); msk++)//2^n次方个状态;
    {
        double sum=0;
        int flag=0;
        for(int i=0; i<N; i++)//一共有n个概率值;   
        {
            if(msk&(1<<i))  //选中一个二进制位,看用了哪些概率值;
            //即这个状态对应几个概率值;
            {
                ++flag;//计数;
                sum+=a[i];//概率值的和;
            }
        }
        if(flag&1)ans+=1.0/sum;//若是奇数;
        //奇加偶减
        else ans-=1.0/sum;
    }
    printf("%lf\n",ans);
}

int main()
{
    int N;
    while(~scanf("%d",&N))
    {
        for(int i=0; i<N; i++)
            scanf("%lf",a+i);
        solve(N);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lanshan1111/article/details/82938181
今日推荐