[概率dp] Jzoj P2059 卡牌游戏

题目描述

N个人坐成一圈玩游戏。一开始我们把所有玩家按顺时针从1到N编号。首先第一回合是玩家1作为庄家。每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字为X,则庄家首先把卡片上的数字向所有玩家展示,然后按顺时针从庄家位置数第X个人将被处决即退出游戏。然后卡片将会被放回卡牌堆里并重新洗牌。被处决的人按顺时针的下一个人将会作为下一轮的庄家。那么经过N-1轮后最后只会剩下一个人,即为本次游戏的胜者。现在你预先知道了总共有M张卡片,也知道每张卡片上的数字。现在你需要确定每个玩家胜出的概率。

这里有一个简单的例子:

例如一共有4个玩家,有四张卡片分别写着3,4,5,6.

第一回合,庄家是玩家1,假设他选择了一张写着数字5的卡片。那么按顺时针数1,2,3,4,1,最后玩家1被踢出游戏。

第二回合,庄家就是玩家1的下一个人,即玩家2.假设玩家2这次选择了一张数字6,那么2,3,4,2,3,4,玩家4被踢出游戏。

第三回合,玩家2再一次成为庄家。如果这一次玩家2再次选了6,则玩家3被踢出游戏,最后的胜者就是玩家2.

输入输出格式

输入格式:

第一行包括两个整数N,M分别表示玩家个数和卡牌总数。

接下来一行是包含M个整数,分别给出每张卡片上写的数字。

输出格式:

输出一行包含N个百分比形式给出的实数,四舍五入到两位小数。分别给出从玩家1到玩家N的胜出概率,每个概率之间用空格隔开,最后不要有空格。

输入输出样例

输入样例#1:

5 5
2 3 5 7 11

输出样例#1:

22.72% 17.12% 15.36% 25.44% 19.36%

输入样例#2:

4 4
3 4 5 6

输出样例#2:

25.00% 25.00% 25.00% 25.00%

说明

对于30%的数据,有1<=N<=10

对于50%的数据,有1<=N<=30

对于100%的数据,有1<=N<=50 1<=M<=50 1<=每张卡片上的数字<=50

题解

  • 首先,我们可以设f[i][j]为当前还剩i个人,从庄家开始数第j个人获胜的概率
  • 然后我们可以发现f[1][1]=1.0
  • 考虑一下如何转移,我们可以枚举庄家该轮抽到的牌k,可以得到当前轮被淘汰的人p(a[k]%i)
  • 那么就有三种情况,
  • ①p=j,当前淘汰的人就是j,那么就可以不用转移
  • ②p>j,那么下一轮的庄家就是剩下的i-1里个人的第p个人的下一个,也就是从1开始数起的第i-p+j,转移f[i][j]+=f[i-1][j-p+j]/m
  • ③p<j,那么下一轮的庄家就是从1开始数起的第j-p个,转移f[i][j]+=f[i-1][j-p]/m

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #define N 60
 4 using namespace std;
 5 int n,m,a[N];
 6 double f[N][N];
 7 int main()
 8 {
 9     scanf("%d%d",&n,&m);
10     for (int i=1;i<=m;i++) scanf("%d",&a[i]);
11     f[1][1]=1;
12     for (int i=2;i<=n;i++)
13         for (int j=1;j<=i;j++)
14             for (int k=1;k<=m;k++)
15             {
16                 int p=(a[k]%i!=0)?a[k]%i:i;
17                 if (p>j) f[i][j]+=f[i-1][i-p+j]/m;
18                 if (p<j) f[i][j]+=f[i-1][j-p]/m;
19             }
20     for (int i=1;i<=n;i++) printf("%.2lf%% ",f[n][i]*100.0);
21 }

原文地址:https://www.cnblogs.com/Comfortable/p/10324825.html

时间: 2024-11-01 20:40:20

[概率dp] Jzoj P2059 卡牌游戏的相关文章

[JLOI2013]卡牌游戏 概率DP

[JLOI2013]卡牌游戏 概率DP 题面 \(dfs\)复杂度爆炸,考虑DP.发现决策时,我们只用关心当前玩家是从庄家数第几个玩家与当前抽到的牌是啥.于是设计状态\(f[i][j]\)表示有\(i\)个人时,从庄家数第\(j\)个人的胜率.又因为此时终态确定\(f[1][1]=1\)(只有一个人时那个人胜率为100%),所以倒推回去. 转移时,枚举抽到的牌,算出从庄家数第\(t\)个会出局,那么下一局庄家就是第\(t+1\)个,当前局第\(j\)个就是下一局的第\(j-t(t< j)\)或\

【BZOJ3191】【JLOI2013】卡牌游戏 [DP]

卡牌游戏 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description N个人坐成一圈玩游戏.一开始我们把所有玩家按顺时针从1到N编号.首先第一回合是玩家1作为庄家.每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字为X,则庄家首先把卡片上的数字向所有玩家展示,然后按顺时针从庄家位置数第X个人将被处决即退出游戏.然后卡片将会被放回卡牌堆里并重新洗牌.被处决的人按顺时针的下一个

卡牌游戏

卡牌游戏 个人信息:就读于燕大本科软件工程专业 目前大三; 本人博客:google搜索"cqs_2012"即可; 个人爱好:酷爱数据结构和算法,希望将来从事算法工作为人民作出自己的贡献; 编程语言:C++ 和 java ; 编程坏境:Windows 7 专业版 x64; 编程工具:vs2008; 制图工具:office 2010 powerpoint; 硬件信息:7G-3 笔记本; 真言 敢于承认不足,敢于去接触和学习,同时又沉稳而镇静 题目 百练 1003 How far can y

计蒜客 16877 卡牌游戏

题目链接:https://nanti.jisuanke.com/t/16877 题目大意:桌子上有N堆牌,每堆牌有Si张,每张牌上有个数.小明和小红玩游戏,小红女士优先,每次从任意一个牌堆顶部取出一张,小明长得丑,每次从任意一个牌堆底部取一张.假设他俩都按照最优的方式取牌,那么谁最后得到的所有牌的数字的和大. 解题思路:首先我们考虑牌个数为偶数的几堆,那么你会发现,无论小红选哪儿个,小明只要跟着她选对应牌堆底部的,那么他俩总会各选顶部或底部一半牌,而且无论谁先手都是一样,显然这样也是最优的(我不

TCG卡牌游戏研究:《炉石战记:魔兽英雄传》所做的改变

转自:http://www.gameres.com/665306.html TCG演进史 说到卡牌游戏,大家会联想到什么呢? 是历史悠久的扑克牌.风靡全球的<MTG 魔法风云会>与<游戏王>.结合数位与现实的<三国志大战>.或是在手机上掀起收集热潮的<龙族拼图>和<百万亚瑟王>? 卡牌游戏这个统称,其内容可以跟各式各样的玩法结合,而暴风雪新推出的<炉石战记>(以下简称炉石)所选择的玩法,是让玩家自行组牌.进行对战的「集换式卡牌游戏」(

菜鸟教程 | egret EUI卡牌游戏制作

写在前面 随着越来越多的新人开始接触白鹭引擎,创作属于自己的游戏.考虑到初学者会遇到的一些实际操作问题,我们近期整理推出<菜鸟教程>系列的文档,以便更好的让这些开打着们快速上手,Egret大神们可以忽略此类内容.本文作者是我们技术支持部门的同事"熊猫少女".看文的小伙伴如果有问题可以来白鹭官方论坛与之交流. EUI是一套基于Egret核心显示列表的UI扩展库,它封装了大量的常用UI组件,能够满足大部分的交互界面需求,即使更加复杂的组件需求,您也可以基于EUI已有组件进行组合

JAVA面向对象编程课程设计——UNO卡牌游戏

一.团队介绍 团队名称:吉祥三宝 成员名称 任务分配 个人博客连接 赖慧颖(组长) 嘤 UNO卡牌游戏-个人博客 黄雅静 嘤 UNO卡牌游戏-个人博客 杨鸿漾 嘤 UNO卡牌游戏-个人博客 二.项目Git地址 UNO卡牌游戏 三.项目git提交记录截图 四.前期调查 五.项目功能架构图.主要功能流程图 六.面向对象设计包图.类图 七.项目运行截图或屏幕录制 八.项目关键代码 九.项目代码扫描结果及改正 十.项目总结 原文地址:https://www.cnblogs.com/yhy949/p/12

Luogu2059 卡牌游戏-概率DP

蒟蒻的第一道概率DP.. 先讲一下我最开始yy的一个算法吧: 我们设f[i][j]表示当前进行了i轮,第j个人坐庄的概率是多少. 为什么这么想呢,因为进行了到第n轮后最后一个人必然是庄,同时这就是它的获胜的概率是吧. 可以发现转移也是很好想的.f[i][j]=f[i-1][last]/m . 但是 嗯嗯,last怎么求,好像求不出啊..所以就挂了??唉.. 但是这也是很有启发性的, 我们发现这样搞不出的原因是:它的淘汰的是围绕着庄转一定步数后的数. 而我们无法维护哪些已经被淘汰,所以我们无法继续

P2059 [JLOI2013]卡牌游戏

题目描述 N个人坐成一圈玩游戏.一开始我们把所有玩家按顺时针从1到N编号.首先第一回合是玩家1作为庄家.每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字为X,则庄家首先把卡片上的数字向所有玩家展示,然后按顺时针从庄家位置数第X个人将被处决即退出游戏.然后卡片将会被放回卡牌堆里并重新洗牌.被处决的人按顺时针的下一个人将会作为下一轮的庄家.那么经过N-1轮后最后只会剩下一个人,即为本次游戏的胜者.现在你预先知道了总共有M张卡片,也知道每张卡片上的数字.现在你需要确定每个