关闭

HDU 5816 Hearthstone(状压DP)

122人阅读 评论(0) 收藏 举报
分类:

Description
有一个卡组,有两种卡牌,A牌n张,B牌m张,抽到一张A牌可以从卡组中再抽两张,抽到一张B牌可以给敌人造成一定的伤害,现在告诉敌人的血量P以及m张B牌的伤害值,初始状态可以从卡组中拿一张牌,问有多大概率可以打败敌人(即抽到牌的总伤害值大于等于敌人的血量)
Input
第一行一整数T表示用例组数,每组用例首先输入三个整数p,n,m分别表示敌人血量,A牌数,B牌数,之后m个整数ai表示第i张B牌的伤害值
(T<=10,p<=1000,n+m<=20,0< ai<=1000)
Output
对于每组用例,输出打败敌人的概率(输出最简分数形式)
Sample Input
2
3 1 2
1 2
3 5 10
1 1 1 1 1 1 1 1 1 1
Sample Output
1/3
46/273
Solution
因为最多20张牌,所以想到用一个20位二进制数表示一个状态,用dp[i]表示拿到牌的状态为i是否合法,初始化就是dp[1<< i]=1,i=0,1,…,n+m-1,对于一个状态i,如果已经拿到x张A牌和y张B牌,统计这y张B牌的总伤害,如果大于等于p则后面的牌随意排列都可以打败敌人,那么对答案的贡献就是dp[i]*(n+m-x-y)!,之后通过判断这个状态是否可以继续拿牌来转移到下一个状态,x张A牌可以拿2x张牌,去掉初始手中的一张牌,故若2x-x-y+1>0说明该状态可以接着拿牌,进而枚举这个状态中0的位赋为1即转移到一下状态
Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn ((1<<20)+11)
ll f[maxn];
int cnt[maxn];
ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
void init()
{
    f[0]=1;
    for(int i=1;i<=20;i++)f[i]=1ll*i*f[i-1];
    for(int i=0;i<(1<<20);i++)
    {
        cnt[i]=0;
        for(int j=0;j<20;j++)
            if(i&(1<<j))cnt[i]++;
    }
}
int T,p,n,m,v[22];
ll dp[maxn];
bool check(int x)
{
    int ans=0;
    for(int i=n;i<n+m;i++)
        if(x&(1<<i))ans+=v[i-n];
    if(ans>=p)return 1;
    return 0;
}
int main()
{
    init();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&p,&n,&m);
        for(int i=0;i<m;i++)scanf("%d",&v[i]);
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n+m;i++)dp[1<<i]=1;
        ll ans=0,N=1<<(n+m);
        for(int i=0;i<N;i++)
        {
            int tot=cnt[i],x=cnt[i&((1<<n)-1)],y=tot-x;
            if(check(i))
            {
                ans+=dp[i]*f[n+m-tot];
                continue;
            }
            if(x-y+1<=0)continue;
            for(int j=0;j<n+m;j++)
                if(!(i&(1<<j)))dp[i|(1<<j)]+=dp[i];
        }
        ll g=gcd(ans,f[n+m]);
        printf("%I64d/%I64d\n",ans/g,f[n+m]/g);
    }
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:359581次
    • 积分:19577
    • 等级:
    • 排名:第447名
    • 原创:1663篇
    • 转载:0篇
    • 译文:0篇
    • 评论:61条
    最新评论