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)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...
随机推荐
- 读取Spring的配置文件applicationContext.xml的5种方法
1.利用ClassPathXmlApplicationContext,这种方式配置文件应该放在类包同路径下Java代码: ApplicationContext ct=new ClassPathXmlA ...
- String[] a = new String[]{"1","2"},我如果想增加一个"3"到a中,如何增加?
在java中数组是定长的,当你声明了数组的大小后数组的长度就不能改变在你的程序中,数组的初始化大小为2,a[0]="1";a[1]="2",所以无法产生元素a[ ...
- openURL的使用方法:
openURL的使用方法: view plaincopy toclipboardprint? [[UIApplication sharedApplication] openURL:[NS ...
- jpg Test
- Swift - 简单封装一个工具类模板
创建模板类(封装一个类) 例1:新建一个名字叫做 Product 的类 Product.swift File 的内容 class Product { var name: String var desc ...
- 【翻译一】java-并发
Lesson: Concurrency Computer users take it for granted that their systems can do more than one thing ...
- 在MAVEN仓库中添加ORACLE JDBC驱动
本文转载自 http://www.cnblogs.com/leiOOlei/archive/2013/10/21/3380568.html 因为已经是第二次遇到,所以COPY过来,怕以后别人的BLOG ...
- Python科学计算发行版—Anaconda
Python是一种强大的编程语言,其提供了很多用于科学计算的模块,常见的包括numpy.scipy和matplotlib.要利用Python进行科学计算,就需要一一安装所需的模块,而这些模块可能又依赖 ...
- 多进程程序设计,王明学learn
多进程程序设计 一.函数学习 1.1 创建进程fork 1.1.1 函数原形 pid_t fork(void); 1.1.2 函数功能 创建一个子进程 1.1.3 所属头文件 <unistd.h ...
- Ubuntu14 搭载vim环境查看源码
首先是下载完整的vim74,然后编译安装.遗憾的是当编译时,没有开启图形界面. 在安装新版本的Vim之前,你需要卸载原来安装的老版本Vim,依次在终端下执行下列命令: sudo apt-get rem ...