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)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...
随机推荐
- iOS 开发多线程篇—GCD的常见用法
iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...
- 备忘zookeeper(单机+伪集群+集群)
#下载: #单机模式 解压到合适目录. 进入zookeeper目录下的conf子目录, 复制zoo_sample.cfg-->zoo.cfg(如果没有data和logs就新建):tickTime ...
- EasyUI中控件汉化问题
--BY ZYZ 我在使用EasyUI的过程中,遇到了控件无汉化的情况,如下图. 这么多洋文看着觉得挺烦的.时间居然是月日年格式的,这样可不行,得改. 重写控件代码?别,那能是我这种低级代码C-V客能 ...
- ld: framework not found AGCommon 关于三方库到入 问题解决方案!!
ld: framework not found AGCommon clang:error:linker command failed with exit code 1 (use -v to see ...
- Swift - 状态栏颜色显示(字体、背景)
ios上状态栏 就是指的最上面的20像素高的部分 状态栏分前后两部分,要分清这两个概念,后面会用到: 前景部分:就是指的显示电池.时间等部分: 背景部分:就是显示黑色或者图片的背景部分: 如下图:前景 ...
- Android缓存学习入门
本文主要包括以下内容 利用LruCache实现内存缓存 利用DiskLruCache实现磁盘缓存 LruCache与DiskLruCache结合实例 利用了缓存机制的瀑布流实例 内存缓存的实现 pub ...
- MongoDB增删查改
1.insert db.Customers.insert({ "DateTest":new Date(), "IntTest":32, "Double ...
- win10下安装Ubuntu + 修复Ubuntu引导
如何在已安装 Windows 10 的情况下安装 Linux(Ubuntu 15.04)双系统? - Microsoft Windows - 知乎http://www.zhihu.com/questi ...
- Linux文件系统(inode、block……)
内容源于<鸟哥的Linux私房菜> 认识 EXT2 文件系统 文件系统的特殊观察与操作 文件系统 superblock,inode,block superblock,inode,block ...
- How many Fibs?【sudt 2321】【大数的加法及其比较】
How many Fibs? Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 Recall the definition of t ...