• HDU5816 Hearthstone(状压DP)


    题目

    Source

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

    Description

    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.

    Input

    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.

    Output

    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

     

    分析

    题目大概说有两种卡牌,使用A牌能从牌堆摸两张牌,使用B牌能对对方造成xi点伤害。在你的回合,你从牌堆摸一张牌,问能对对方造成p点及以上伤害的概率。

    要求的其实就是能造成p点以上伤害的牌堆排列数/牌堆全排列数

    全排列而且总数为20,这种就该想到尝试用状压DP。。

    • dp[S]表示已经摸的牌的集合为S的可行排列方案数

    对于一个状态S,我们能从这个集合中已经摸的牌知道还能摸几张,即A的数目 * 2 - A的数目 - B的数目 + 一开始能摸的一张牌

    考虑状态的转移,我是用我为人人实现的:从小到大枚举状态S,判断S是否合法,即S的方案数不为0且还能摸牌,然后通过S去更新S+i(i∉S)状态的值。另外如果S能造成的伤害已经大于等于p了,那就没必要去更新它能转移到的状态,因为还剩下的牌直接求全排列计算其贡献,这样也能避免重复计算。

    最后就循环遍历各个合法的状态累加贡献,这个贡献就是dp值 * 还没摸的牌的全排列数。这样就求出能造成p点以上伤害的牌堆排列数,再和全排列数用GCD搞搞输出答案即可。

    代码

    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    long long fact[22]={1};
    
    long long gcd(long long a,long long b){
    	if(b==0) return a;
    	return gcd(b,a%b);
    }
    
    int p,n,m,N,x[22];
    long long d[1<<20];
    
    int main(){
    	for(int i=1; i<22; ++i) fact[i]=fact[i-1]*i;
    	int t;
    	scanf("%d",&t);
    	while(t--){
    		scanf("%d%d%d",&p,&n,&m);
    		N=n+m;
    		for(int i=n; i<N; ++i){
    			scanf("%d",&x[i]);
    		}
    		
    		memset(d,0,sizeof(d));
    		d[0]=1;
    		for(int s=0; s<(1<<N); ++s){
    			if(d[s]==0) continue;
    			
    			int A=0,B=0,damage=0;
    			for(int i=n; i<N; ++i){
    				if(s>>i&1){
    					damage+=x[i];
    					++B;
    				}
    			}
    			if(damage>=p) continue;
    			for(int i=0; i<n; ++i){
    				if(s>>i&1) ++A;
    			}
    			
    			if(A-B+1<=0) continue;
    			
    			for(int i=0; i<N; ++i){
    				if(s>>i&1) continue;
    				d[s^(1<<i)]+=d[s];
    			}
    		}
    		
    		long long xx=0,yy=fact[N];
    		for(int s=0; s<(1<<N); ++s){
    			if(d[s]==0) continue;
    			int A=0,B=0,damage=0;
    			for(int i=n; i<N; ++i){
    				if(s>>i&1){
    					damage+=x[i];
    					++B;
    				}
    			}
    			for(int i=0; i<n; ++i){
    				if(s>>i&1) ++A;
    			}
    			if(damage>=p){
    				xx+=d[s]*fact[N-A-B];
    			}
    		}
    		long long g=gcd(xx,yy);
    		printf("%I64d/%I64d
    ",xx/g,yy/g);
    	}
    	return 0;
    }
    
  • 相关阅读:
    English trip -- VC(情景课)9 A Get ready
    English trip -- Review Unit8 Work 工作
    English trip -- VC(情景课)8 D Reading
    bzoj 4238 电压
    luoguP2154 [SDOI2009]虔诚的墓主人
    bzoj 2225 [Spoj 2371]Another Longest Increasing
    bzoj 4383 [POI2015]Pustynia
    luogu3706 [SDOI2017]硬币游戏
    luogu P6125 [JSOI2009]有趣的游戏
    luogu4443 coci 2017 Dajave
  • 原文地址:https://www.cnblogs.com/WABoss/p/5754721.html
Copyright © 2020-2023  润新知