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\n",xx/g,yy/g);
}
return 0;
}
HDU5816 Hearthstone(状压DP)的更多相关文章
- 多校7 HDU5816 Hearthstone 状压DP+全排列
多校7 HDU5816 Hearthstone 状压DP+全排列 题意:boss的PH为p,n张A牌,m张B牌.抽取一张牌,能胜利的概率是多少? 如果抽到的是A牌,当剩余牌的数目不少于2张,再从剩余牌 ...
- hdu-5816 Hearthstone(状压dp+概率期望)
题目链接: Hearthstone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ...
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
- nefu1109 游戏争霸赛(状压dp)
题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...
- poj3311 TSP经典状压dp(Traveling Saleman Problem)
题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...
- [NOIP2016]愤怒的小鸟 D2 T3 状压DP
[NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...
- 【BZOJ2073】[POI2004]PRZ 状压DP
[BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...
- bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)
数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...
- HDU 1074 Doing Homework (状压dp)
题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...
随机推荐
- 模拟赛1030d2
他[问题描述]一张长度为N的纸带, 我们可以从左至右编号为0 − N( 纸带最左端标号为0). 现在有M次操作, 每次将纸带沿着某个位置进行折叠, 问所有操作之后纸带的长度是多少.[输入格式]第一行两 ...
- Javascript和Java获取各种form表单信息的简单实例
大家都知道我们在提交form的时候用了多种input表单.可是不是每一种input表单都是很简单的用Document.getElementById的方式就可以获取到的.有一些组合的form类似于che ...
- gzip
gzip -c 将输出写到标准输出上,并保留原文本 gzip * : 把当前目录中的每个文件压缩成.gz文件 [root@NB gzip]# ls mysql-bin. mysql-bin..tar ...
- CLR via C#(09)-扩展方法
对于一些现成的类,如果我们想添加一些新的方法来完善功能,但是不想改变已有的封装,也不想使用派生类,那么该怎么办呢?这里我们可以使用扩展方法. 一见钟情--初识扩展 扩展方法使您能够向现有类型“添加”方 ...
- Delphi中exit、break、continue等跳出操作的区别
Delphi中表示跳出的有break,continue,abort,exit,halt,runerror等 1.break 强制退出最近的一层循环(注意:只能放在循环里:而且是只能跳出最近的一层循环) ...
- Oracle 数据泵文件
数据泵文件 expdp介绍 EXPDP命令行选项1. ATTACH该选项用于在客户会话与已存在导出作用之间建立关联.语法如下ATTACH=[schema_name.]job_nameSchema_na ...
- 把VSO作为GitHub上JavaScript项目的免费CI服务器
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:微软变得更加开放后,走向开放的不仅有.NET运行时.IDE工具,还有ALM服务器核心组 ...
- AIX下禁止crs随ha启动而启动
/etc/init.crs enable /etc/init.crs disable 查看目前crs是enable还是disable状态 状态记录在一个文本文件里 /etc/oracle/scls_ ...
- WPF之MVVM(Step2)——自己实现DelegateCommand:ICommand
在自己实现MVVM时,上一篇的实现方式基本是不用,因其对于命令的处理不够方便,没写一个命令都需要另加一个Command的类.此篇主要介绍DelegateCommand来解决上面所遇到的问题. 首先,我 ...
- php随机生成验证码
我们经常需要服务器向前端发送验证码,验证码需要随机产生,下面的用简单的代码实现了这一过程: <?php $pool='0123456789abcdefghijklmnopqrstuvwxyzAB ...