• HDU 5816 Hearthstone 概率dp


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5816

    Hearthstone

    Time Limit: 2000/1000 MS (Java/Others)
    Memory Limit: 65536/65536 K (Java/Others)
    #### 问题描述 > Hearthstone is an online collectible card game from Blizzard Entertainment. Strategies and luck are the most important factors in this game. When you suffer a desperate situation and your only hope depends on the top of the card deck, and you draw the only card to solve this dilemma. We call this "Shen Chou Gou" in Chinese. > Now you are asked to calculate the probability to become a "Shen Chou Gou" to kill your enemy in this turn. To simplify this problem, we assume that there are only two kinds of cards, and you don't need to consider the cost of the cards. > > - A-Card: If the card deck contains less than two cards, draw all the cards from the card deck; otherwise, draw two cards from the top of the card deck. > - B-Card: Deal X damage to your enemy. > > Note that different B-Cards may have different X values. > At the beginning, you have no cards in your hands. Your enemy has P Hit Points (HP). The card deck has N A-Cards and M B-Cards. The card deck has been shuffled randomly. At the beginning of your turn, you draw a card from the top of the card deck. You can use all the cards in your hands until you run out of it. Your task is to calculate the probability that you can win in this turn, i.e., can deal at least P damage to your enemy.

    输入

    The first line is the number of test cases T (T<=10).
    Then come three positive integers P (P<=1000), N and M (N+M<=20), representing the enemy’s HP, the number of A-Cards and the number of B-Cards in the card deck, respectively. Next line come M integers representing X (0<X<=1000) values for the B-Cards.

    输出

    For each test case, output the probability as a reduced fraction (i.e., the greatest common divisor of the numerator and denominator is 1). If the answer is zero (one), you should output 0/1 (1/1) instead.

    样例

    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

    题意

    对手的血量为p,你有奥术牌n张,火球牌m张,一开始你可以任抽一张牌,之后如果抽到奥术,你就还可以抽两张牌,如果抽到火球,你就能给对手ai点伤害。
    问最后打死对手的概率。

    题解

    我们可以先考虑从n+m张牌中恰好抽出k张奥术的概率,然后再去考虑用k+1张火球打死对手的概率。
    队友用O(1<<(n+m))的复杂度强行模拟了牌堆取数的情况。orzorzorz

    代码

    #include<map>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=(a);i<(b);i++)
    
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=1e9;
    const LL INFL=0x3f3f3f3f3f3f3f3fLL;
    const double eps=1e-8;
    
    //start----------------------------------------------------------------------
    
    const int maxm=22;
    const int maxn=22;
    int hp,n,m;
    
    int arr[maxn];
    LL sumao[maxn];
    LL sumhuo[maxn];
    LL one[(1<<maxn)+10];
    LL cntao,cnthuo[maxn];
    
    LL gcd(LL a,LL b) {
    	return b==0?a:gcd(b,a%b);
    }
    
    void init() {
    	cntao=0;
    	clr(cnthuo,0);
    	clr(sumao,0);
    	clr(sumhuo,0);
    }
    
    struct Fenshu {
    	LL a,b;
    	Fenshu(LL a,LL b):a(a),b(b) {}
    	Fenshu() {
    		a=0;
    		b=1;
    	}
    };
    
    Fenshu add(Fenshu fs1,Fenshu fs2) {
    	LL ta=fs1.a*fs2.b+fs1.b*fs2.a;
    	LL tb=fs1.b*fs2.b;
    	LL g=gcd(ta,tb);
    	return Fenshu(ta/g,tb/g);
    }
    Fenshu mul(Fenshu fs1,Fenshu fs2) {
    	LL ta=fs1.a*fs2.a;
    	LL tb=fs1.b*fs2.b;
    	LL g=gcd(ta,tb);
    	return Fenshu(ta/g,tb/g);
    }
    
    void pre() {
    	clr(one,0);
    	rep(i,0,(1<<(maxm))) {
    		rep(j,0,maxm) {
    			if(i&(1<<j)) one[i]++;
    		}
    	}
    }
    
    int main() {
    	pre();
    	int tc;
    	scanf("%d",&tc);
    	while(tc--) {
    		init();
    		scanf("%d%d%d",&hp,&n,&m);
    		rep(i,0,m) scanf("%d",arr+i);
    		//从n+m张牌中恰好能取出k张奥术的总数,存在sumao[k]里面。 
    		rep(i,0,1<<(n+m)) {
    			if(one[i]!=n) continue;
    			cntao++;
    			int cnt=1,sum=0;
    			for(int j=0; cnt&&j<(n+m); j++) {
    				cnt--;
    				if(i&(1<<j)) {
    					sum++;
    					cnt+=2;
    
    				}
    			}
    			sumao[sum]++;
    		}
    		//从m张火球中取出k张并且打死对手的总数,存在sumhuo[k]里面。 
    		rep(i,0,1<<m) {
    			int cnt=0,sum=0;
    			rep(j,0,m) {
    				if(i&(1<<j)) {
    					cnt++;
    					sum+=arr[j];
    				}
    			}
    			cnthuo[cnt]++;
    			if(sum>=hp) {
    				sumhuo[cnt]++;
    			}
    		}
    		Fenshu ans;
    		rep(i,0,n+1) {
    			//i张奥术能让我们抽i+1张火球。 
    			Fenshu tmp;
    			if(i<m) tmp=mul(Fenshu(sumao[i],cntao),Fenshu(sumhuo[i+1],cnthuo[i+1]));
    			//最多只能抽到m张火球 
    			else tmp=mul(Fenshu(sumao[i],cntao),Fenshu(sumhuo[m],cnthuo[m]));
    			ans=add(ans,tmp);
    		}
    		printf("%lld/%lld
    ",ans.a,ans.b);
    	}
    	return 0;
    }
    
    //end-----------------------------------------------------------------------
  • 相关阅读:
    Sass安装与Webstorm File Watcher配置
    AngularJS ng-disabled在a内无效
    AngularJS 指令(Directivce )一
    Bus Hound 检测USB数据收发的教程
    STM32Cumebx HAL库实现STM32 USB虚拟串口的收发
    Docker学习笔记六:Docker搭建企业级私有仓库
    Docker学习笔记五:Docker生成jenkins容器,支持Java Web项目持续集成、持续部署
    Linux学习笔记一:Linux配置java环境变量
    Docker学习笔记四:Docker镜像、容器管理工具shipyard
    Redis学习笔记一:Redis安装
  • 原文地址:https://www.cnblogs.com/fenice/p/5763244.html
Copyright © 2020-2023  润新知