博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Gym 101933E(状态压缩+记忆化搜索)
阅读量:5168 次
发布时间:2019-06-13

本文共 3231 字,大约阅读时间需要 10 分钟。

题面:

E. Explosion Exploit

time limit per test

2.0 s

memory limit per test

256 MB

input

standard input

output

standard output

In a two player card game, you have nn minions on the board and the opponent has mm minions. Each minion has a health between 11 and 66.

You are contemplating your next move. You want to play an "Explosion" spell which deals dd units of damage randomly distributed across all minions. The damage is dealt one unit at a time to some remaining minion on the board. Each living minion (including your own) has the same chance of receiving each unit of damage. When a minion receives a unit of damage, its health is decreased by one. As soon as the health of a minion reaches zero, it is immediately removed from the board, before the next damage is dealt. If there are no minions left on the board, any excess damage caused by the spell is ignored.

Given the current health of all minions, what is the probability that the Explosion will remove all of the opponent's minions? Note that it does not matter if all your own minions die in the process as well, and the damage continues to be dealt even if all your own minions are gone.

Input

The first line of input contains the three integers nn, mm, and dd (1≤n,m≤51≤n,m≤5, 1≤d≤1001≤d≤100). Then follows a line containing nn integers, the current health of all your minions. Finally, the third line contains mm integers, the current health of all the opponent's minions. All healths are between 11 and 66 (inclusive).

Output

Output the probability that the Explosion removes all the opponent's minions, accurate up to an absolute error of 10−610−6.

Examples

input

Copy

1 2 221 1

output

Copy

0.33333333

input

Copy

2 3 123 24 2 3

output

Copy

0.13773809

题意:

    你有n个士兵,敌方有m个士兵,每一个士兵都有一定的血量(最大为6),如果血量归零,则证明该士兵死亡。现在有d点伤害,每一点伤害都会以等概率分配给任意一个人。现在问你,地方的m个士兵全都阵亡的概率。

题目分析:

    首先我们可以发现,因为每个士兵的血量最大为6,且敌我双方的士兵数均为5,因此我们考虑可以用搜索的方法去解决。

    因为士兵的总血量的状态比较少,因此我们可以考虑用一个12位的long long的每一位去存储每一种血量的个数。此时,这每一个12位的long long整型就唯一代表了一种状态。而又因为在搜索的过程中,每一种曾经访问过的状态所对应的概率必定是唯一的,因此我们只需要用记忆化的形式对曾经出现过的结果记进行记录,以达到剪枝的作用。

    因为我们要记录的是敌军死亡的概率,因此,我们可以优先将敌军的6种血量置于12位long long的高位,这样,当我们访问到的状态值<1000000,则代表已经敌军已经已经死亡,即可直接跳出递归(又一个剪枝)。

    最后只需要将相应的概率相乘并相加即为答案。

代码:

#include 
using namespace std;typedef unsigned long long ll;int mp[2][10];unordered_map
dp;//充当记忆化数组ll GetSta(){//获取状态 ll res=0; for(int i=1;i<=6;i++) res*=10,res+=mp[1][i]; for(int i=1;i<=6;i++) res*=10,res+=mp[0][i]; return res;}double dfs(ll sta,int limit){ if(dp.count(sta)) return dp[sta];//如果该状态曾经访问过,则直接调用结果 if(sta<1000000) return 1;//如果该状态的值<1000000,则证明敌人已死,返回1 if(limit==0) return 0; int cnt=0; for(int i=0;i<2;i++)//获取总人数 for(int j=1;j<=6;j++) cnt+=mp[i][j]; double res=0; for(int i=0;i<2;i++){ for(int j=1;j<=6;j++){ if(!mp[i][j]) continue; mp[i][j]--; mp[i][j-1]++; ll newsta=GetSta(); double tmp=dfs(newsta,limit-1);//dfs求解下一层的答案 dp[newsta]=tmp; mp[i][j]++;//回溯 mp[i][j-1]--; res+=1.0*mp[i][j]/cnt*tmp;//统计概率 } } return res;}int main(){ int n,m,d,num; scanf("%d%d%d",&n,&m,&d); for(int i=0;i

 

转载于:https://www.cnblogs.com/Chen-Jr/p/11007169.html

你可能感兴趣的文章
面试题24:二叉排序树的后序遍历序列
查看>>
用尽洪荒之力整理的Mysql数据库32条军规(转)
查看>>
机器学习专题(一)——KNN算法的python实现
查看>>
什么才是成功的项目,什么才是成功的人生?
查看>>
php GD 圆图 -处理成圆图片
查看>>
『ORACLE』 SQL语句简单应用(三)(11g)
查看>>
第十二天 SQL语句 查询
查看>>
Usvn迁移
查看>>
Python-前言
查看>>
linux基础-第六单元 用户、群组和权限
查看>>
UNIX环境高级编程——标准I/O库
查看>>
什么是W3C标准
查看>>
看板与Scrum:哪个更适合你的团队?
查看>>
php的setcookie
查看>>
用python 实现生成双色球小程序
查看>>
python webdriver安装
查看>>
react全局的公共组件-------弹框 (Alert)
查看>>
第一次作业+105032014162
查看>>
如何优化在搜索引擎上的友好度
查看>>
ResponseUtil数据传递至前端
查看>>