写在前面

  • 感谢巨佬 yu__xuan 的帮助!
  • 原本题解区的大佬们大都写的九层循环,其实此题如果写成状压,可以将这九层循环写成一层,非但简洁、代码可读性强,常数也比直接九维 dp 小。

算法思路

由于每一行都只有四张牌,考虑写成五进制状压 dp。

设当前状态为 \(t\),则五进制状压 dp 取出第 \(i\) 行的状态的方式:\(\frac{t}{5^i}\!\!\!\!\mod 5\)(视初始行为第 \(0\) 行)

因此,若设第 \(i\) 行的第 \(j\) 张牌的点数为 \(a_{i,j}\),则状态转移方程为:

\[\large f_{t - 5^{p1} - 5^{p2}} = f_{t - 5^{p1} - 5^{p2}} + f_t \times p(a_{p1,\frac{t}{5^p1}\!\!\!\!\mod 5} = a_{p2,\frac{t}{5^p2}\!\!\!\!\mod 5})
\]

其中 \(p\) 为此次转移的概率,等于从状态 \(t\) 能转移到的状态数总和的倒数。

边界条件: \(f_{5^9 - 1} = 1\)。

倒序枚举所有状态,每当找到一个当前答案不为 \(0\) 的状态时,先统计出它能更新到的状态数,算出转移的概率 \(P\),然后用该状态去更新它所能更新到的状态的答案。

由于一直在拿牌,表示状态的变量会逐渐减小,倒序枚举状态时可行的。

Tips

  • 读入的时候用类似于快速读入的方式过滤一下不合法字符可以极大地简化读入部分的代码。

  • 扑克牌的点数不等同于真实的扑克牌的点数,因此统计的时候不需要再对点数进行处理,直接将 char 转成 int 存下来即可。

Code

#include<bits/stdc++.h>
#define LF double const int pow5[] = {1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125};
using namespace std; LF f[1953125];
int a[10][5]; char Getch() {char ch = getchar(); while((!isalpha(ch)) && (!isdigit(ch))) ch = getchar(); return ch;} int main() {
for(register int i = 0; i < 9; ++i) {
for(register int j = 1; j <= 4; ++j) {
a[i][j] = Getch(); Getch();
}
}
f[1953124] = 1.0;
for(register int t = pow5[9] - 1; t >= 0; --t) {
if(f[t] == 0) continue;
LF choise = 0;
for(register int p1 = 0; p1 < 9; ++p1) {
for(register int p2 = p1 + 1; p2 < 9; ++p2) {
if((a[p1][t / pow5[p1] % 5] == a[p2][t / pow5[p2] % 5]) && ((t / pow5[p1] % 5) > 0) && ((t / pow5[p2] % 5) > 0)) choise++;
}
}
LF P = f[t] * 1.0 / choise;
for(register int p1 = 0; p1 < 9; ++p1) {
for(register int p2 = p1 + 1; p2 < 9; ++p2) {
if((a[p1][t / pow5[p1] % 5] == a[p2][t / pow5[p2] % 5]) && ((t / pow5[p1] % 5) > 0) && ((t / pow5[p2] % 5) > 0)) {
f[t - pow5[p1] - pow5[p2]] += P;
}
}
}
}
printf("%lf", f[0]);
return 0;
}

P1837 单人纸牌的更多相关文章

  1. P1837 单人纸牌_NOI导刊2011提高(04)

    题目描述 单人纸牌游戏,共36张牌分成9叠,每叠4张牌面向上.每次,游戏者可以从某两个不同的牌堆最顶上取出两张牌面相同的牌(如黑桃10和梅花10)并且一起拿走.如果最后所有纸牌都被取走,则游戏者就赢了 ...

  2. 单人纸牌_NOI导刊2011提高(04)

    单人纸牌 时间限制: 1 Sec  内存限制: 128 MB 题目描述 单人纸牌游戏,共 36 张牌分成 9 叠,每叠 4 张牌面向上.每次,游戏者可以从某两个不同的牌堆最顶上取出两张牌面相同的牌(如 ...

  3. linux快捷键及主要命令(转载)

    作者:幻影快递Linux小组 翻译 2004-10-05 22:03:01 来自:Linux新手管理员指南(中文版) 5.1 Linux基本的键盘输入快捷键和一些常用命令 5.2 帮助命令 5.3 系 ...

  4. code vs 1098 均分纸牌(贪心)

    1098 均分纸牌 2002年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解   题目描述 Description 有 N 堆纸牌 ...

  5. C语言-纸牌计算24点小游戏

    C语言实现纸牌计算24点小游戏 利用系统时间设定随机种子生成4个随机数,并对4个数字之间的运算次序以及运算符号进行枚举,从而计算判断是否能得出24,以达到程序目的.程序主要功能已完成,目前还有部分细节 ...

  6. 一起来做webgame,《Javascript蜘蛛纸牌》

    不得不说,做游戏是会上瘾的,这次带来的是win系统上的经典游戏<蜘蛛纸牌>,不能完美,但求一玩 移牌 0 次 Javascript game_蜘蛛纸牌 正在努力加载... // " ...

  7. 洛谷 P1031 均分纸牌 Label:续命模拟QAQ

    题目描述 有 N 堆纸牌,编号分别为 1,2,…, N.每堆上有若干张,但纸牌总数必为 N 的倍数.可以在任一堆上取若于张纸牌,然后移动. 移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 ...

  8. 斯坦福iOS7公开课1-3笔记及纸牌Demo

    1.MVC Model:模型 描述程序是什么,例如数据库操作之类的行文以及纸牌Demo里纸牌玩法都是写在Model这一层,通过Notification和KVO(后续文章会介绍)两种方式与Control ...

  9. [CareerCup] 8.1 Implement Blackjack 实现21点纸牌

    8.1 Design the data structures for a generic deck of cards. Explain how you would subclass the data ...

随机推荐

  1. jQuery是如何实现?

    jQuery是什么? jQuery就是一个javascript的类库,函数库. jQuery是如何实现的? jQuery采用的是构造函数模式进行开发的,jQuery是一个类 常用的方法(CSS.属性. ...

  2. java开发手册之哨兵语句

    if(条件判断1){ return; } if(条件判断2){ return; } //do  another things 注意事项:一定要避免多个if else 判断 带来逻辑混乱 可读性变差

  3. 智能BPOS小票模板字体的使用

    关于伯俊智能BPOS零售小票模板的设置,常用字体"黑体"."宋体"."Arial"这几个字体,在设置的时候看似没有问题, 但是在正真使用打印 ...

  4. 风炫安全WEB安全学习第二十一节课 存储型XSS讲解

    风炫安全WEB安全学习第二十一节课 存储型XSS讲解 存储型XSS演示 存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,加入代码,如果没有过滤或过滤不严,那么这些代码将储存 ...

  5. 算法设计与分析 - 主定理Master theorem (分治法递推时间复杂度)

    英文原版不上了 直接中文 定义 假设有递推关系式T(n)=aT(n/b)+f(n) 其中n为问题规模 a为递推的子问题数量 n/b为每个子问题的规模(假设每个子问题的规模基本一样) f(n)为递推以外 ...

  6. LeetCode106 从中序和后序序列构造二叉树

    题目描述: 根据一棵树的中序遍历与后序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [ ...

  7. 【Flutter】容器类组件之装饰容器

    前言 DecoratedBox可以在其子组件绘制前后绘制一些装饰,例如背景,边框,渐变等. 接口描述 const DecoratedBox({ Key key, // 代表要绘制的装饰 @requir ...

  8. Flutter 基础组件:Widget简介

    概念 在Flutter中几乎所有的对象都是一个Widget.与原生开发中"控件"不同的是,Flutter中的Widget的概念更广泛,它不仅可以表示UI元素,也可以表示一些功能性的 ...

  9. python作业完成简单的文件操作

    题目 请创建以学号命名的目录,在该目录中创建名称为file1.txt的文件,并将自己的个人信息(序号.姓名以及班级)等写入该文件:然后并读取文件中的内容到屏幕上:接着重新命名该文件为file2.txt ...

  10. Manjaro Linux 5.9.11-3安装和配置全局截图工具FlameShot教程

    背景说明 截图工具是日常适用频率较高的一种系统工具,在Linux下也有不少常用截图工具,如deepin-screenshot等,但是今天我们要介绍的是FlameShot--一款更加精致的Linux全局 ...