From 08c804bb361ae3bc26ff55cc9c79c69940f4ae35 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=BB=84=E6=B5=B7?= <10402852@qq.com>
Date: Mon, 25 Dec 2023 07:48:44 +0800
Subject: [PATCH] 'commit'
---
TangDou/AcWing/Math/QiWang/217.drawio | 1 -
TangDou/AcWing/Math/QiWang/217.md | 206 ------------------
TangDou/AcWing/Math/QiWang/217_DaoTui.cpp | 44 ----
TangDou/AcWing/Math/QiWang/217_ZhengTui.cpp | 59 -----
TangDou/AcWing/Math/QiWang/218.md | 152 -------------
TangDou/AcWing/Math/QiWang/218_dp.cpp | 48 ----
.../T5/QiWang/218.cpp} | 0
TangDou/AcWing_TiGao/T5/QiWang/218_dfs.cpp | 70 ------
TangDou/AcWing_TiGao/T5/QiWang/218_dp.cpp | 48 ----
9 files changed, 628 deletions(-)
delete mode 100644 TangDou/AcWing/Math/QiWang/217.drawio
delete mode 100644 TangDou/AcWing/Math/QiWang/217.md
delete mode 100644 TangDou/AcWing/Math/QiWang/217_DaoTui.cpp
delete mode 100644 TangDou/AcWing/Math/QiWang/217_ZhengTui.cpp
delete mode 100644 TangDou/AcWing/Math/QiWang/218.md
delete mode 100644 TangDou/AcWing/Math/QiWang/218_dp.cpp
rename TangDou/{AcWing/Math/QiWang/218_dfs.cpp => AcWing_TiGao/T5/QiWang/218.cpp} (100%)
delete mode 100644 TangDou/AcWing_TiGao/T5/QiWang/218_dfs.cpp
delete mode 100644 TangDou/AcWing_TiGao/T5/QiWang/218_dp.cpp
diff --git a/TangDou/AcWing/Math/QiWang/217.drawio b/TangDou/AcWing/Math/QiWang/217.drawio
deleted file mode 100644
index d9a22c8..0000000
--- a/TangDou/AcWing/Math/QiWang/217.drawio
+++ /dev/null
@@ -1 +0,0 @@
-5VpLc9owEP41zLSHMtbLj2NDHj00M+mkbdLePFiAEmNRI4rJr6+MZbAlB0gCVgkzHLwraWV9+3m1WtFBvXF2lYaT0TWPaNyBTpR10HkHQoAh7OQ/J1oUGt8jhWKYskh1Witu2RNVSkdpZyyi01pHwXks2KSu7PMkoX1R04Vpyuf1bgMe12edhENqKG77YWxq71gkRkrrErxu+ELZcFRODdygaBmHZW+1lOkojPi8okIXHdRLORfF0zjr0ThHrwSmGHf5TOvqzVKaiF0GDB7cy3F2+fPp4QpP/izI7Ovi/pOy8jeMZ2rFD+ptxaLEQJqRcEvhbD5igt5Own7eMpcel7qRGMdSAvIxnE4KHwxYRuWsZ1OR8scVcFhqBjwRyssQlbKaqmFF5evRVNCsolIrvKJ8TEW6kF1Ua4AV2opvIFDyfO09olSjit9KXaj4MlxZXiMqHxSozQBf9JxfT78ZFL9/XH0PxfUw/PatAeAM2EbYgLMB9GcRdoM6wtCxjDA0EUZHjbDneTWEEbKMMDIRhkeNcKBxGNvmMDYRfjxqhH2/jjCxzWFiIJwcNcAu1AC2TWHXANjEN4k+5zmZlPpxOJ2yfh3WlM+SKMfz3NEQ9KRMMybuVVv+/Ct/7hIlnWeVpvNFKSRyaffK/FKojMrF9bClVI4z/VkshkZGumgkK1M+S/t0e84lwnRIxbbUwSTAjg5OaRwK9rf+uk1eVzPccCYXst6EHC1EehpximWqUdW0UzdENENQM1TgYBhaknC17Nfz0jN4edeQgckPUdTJWFCgx2OeSk3CkzwuDFgca6owZsMkZ7TkAZX6s/yzZvIE8Vk1jFkUxc8Flc2U30cg1uIE8M044TbQCB0qTvitxYku9CuhArwmULw4TORGb2jKJFY5GZa9LIQOaDN0BNoXLw3vJ3RApBk6cOgI2qMq2Zmp/8XWhK3yy8V1Wug5za788n3YdT3PdQMijWpWEfa6aHn4klsfQq7jtsq9sgB2ePKBN1BvFTYrKdUugdMCZZFVypZlz7dSNgBBTlnfgW7g5QyumSXY6WIMCCI+CggO2mWsWeo6VLh8wQlgA2e1MwHcwtmltJ+9fVOVZSuRiVUiBxtCpsztq40owK8jOXBg/XPBoN0zAzBrinum8u603HZU3SMD8TEwEDj6yVTPCnelmavXqFo+mQKzrnqogPmC/PK1W/q+8tJNtyj/NzNPIy81S9Ut7PJvyEs9WI+nEi+7+zw8Bi6/oyhrVv7vGi4IT6YACD3LBUBg3hTcNdwnvluHGJ8Wari6adcjTTVy8/7x3XrE9zSHNPxppF2HmEXywYcMfDwdl7hAcwm27RKzGCxdgk7IJZ7216rVRZ4tl5Tz110CT8gl+t6Obe/t0KwBSpc8npBL9DsrQg7mEimu/z1apMvrP+Gii38=
\ No newline at end of file
diff --git a/TangDou/AcWing/Math/QiWang/217.md b/TangDou/AcWing/Math/QiWang/217.md
deleted file mode 100644
index 83cfec7..0000000
--- a/TangDou/AcWing/Math/QiWang/217.md
+++ /dev/null
@@ -1,206 +0,0 @@
-##[$AcWing$ $217$. 绿豆蛙的归宿](https://www.acwing.com/problem/content/description/219/)
-
-### 一、题目描述
-给出一个有向无环的连通图,起点为 $1$ ,终点为 $N$,每条边都有一个长度。
-
-数据保证从起点出发能够到达图中所有的点,图中所有的点也都能够到达终点。
-
-绿豆蛙从起点出发,走向终点。
-
-到达每一个顶点时,如果有 $K$ 条离开该点的道路,绿豆蛙可以选择任意一条道路离开该点,并且走向每条路的概率为 $1/K$。
-
-现在绿豆蛙想知道,从起点走到终点所经过的路径总长度的 **期望** 是多少?
-
-**输入格式**
-第一行: 两个整数 $N,M$,代表图中有 $N$ 个点、$M$ 条边。
-
-第二行到第 $1+M$ 行: 每行 $3$ 个整数 $a,b,c$,代表从 $a$ 到 $b$ 有一条长度为 $c$ 的有向边。
-
-**输出格式**
-输出从起点到终点路径总长度的 **期望值**,结果四舍五入保留两位小数。
-
-**数据范围**
-$1≤N≤10^5,1≤M≤2N$
-
-**输入样例:**
-```cpp {.line-numbers}
-4 4
-1 2 1
-1 3 2
-2 3 3
-3 4 4
-```
-
-**输出样例:**
-```cpp {.line-numbers}
-7.00
-```
-
-### 二、数学期望
-
-**[视频讲解 数学期望及性质](https://www.ixigua.com/6978816201023554061)**
-
-**[参考题解](https://www.acwing.com/solution/content/63508/)**
-
-首先明白一点:到达某个结果的期望值 = 这个结果 * 从起始状态到这个状态的概率
-
-$Q:$什么意思呢?
-
-如图:
-
-
-我们计算从$1$号点到$3$号点的期望距离
-
-路径$1$. $\displaystyle 1−>3:E_1=2×\frac{1}{2}=1$
-
-路径$2$. $\displaystyle 1−>2−>3:E_2=1×\frac{1}{2}+3×\frac{1}{2}×1=2$
-
-这里路径$2$中从$1$到$2$概率为$\displaystyle \frac{1}{2}$,但单看从$2$到$3$概率就是$1$,但是从$1$到$3$那就是从($1$到$2$的概率)$\displaystyle \frac{1}{2}$×$1$($2$到$3$的概率)=$\displaystyle \frac{1}{2}$。
-
-所以从 点$1$ 到 点$3$ 的数学期望值=$1+2=3$
-
-总结:概率是叠乘的
-
-
-本题有 **正推** 和 **倒推** 两种写法:
-
-### 二、正推法
-
-
-设:
-- $a_1, a_2, a_3 … a_k$ 到 $j$ 的权值为 $w_1, w_2, w_3 … w_k$,
-- 从起点到这$k$个点的概率为:$p_1, p_2, p_3 … p_k$
-- 每个点的出度为:$out_1, out_2, out_3, … , out_k$
-
-这里的$1\sim k$个点的从起点的到该点的概率一定是确定的,也就是说这个点的概率是被更新完的,即此时这个点的入度为$0$!
-
-那么就有:
-$$f(i):表示从起点到i点的期望距离$$
-$$f(j)=\frac{f(1)+w_1\times p_1}{out_1}+\frac{f(2)+w_2\times p_2}{out_2}+\frac{f(3)+w_3\times p_3}{out_3}+...+\frac{f(k)+w_k\times p_k}{out_k} $$
-
-#### 正推代码
-```cpp {.line-numbers}
-#include
-using namespace std;
-const int N = 1e5 + 10, M = 2 * N;
-
-//邻接表
-int h[N], e[M], ne[M], w[M], idx;
-void add(int a, int b, int c) {
- e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
-}
-
-int n, m; // n个顶点,m条边
-
-int out[N], in[N]; //出度,入度
-double f[N], g[N]; // f:数学期望结果 g:概率
-
-void topsort() {
- queue q;
- //起点为1,起点的概率为100%
- q.push(1);
- g[1] = 1.0;
- f[1] = 0.0;
-
- // DAG,执行拓扑序,以保证计算的顺序正确,确保递归过程中,前序数据都已处理完毕
- while (q.size()) {
- auto u = q.front();
- q.pop();
-
- for (int i = h[u]; ~i; i = ne[i]) { //枚举的是每边相邻边
- int j = e[i]; //此边,一端是t,另一端是j
- //此边边条w[i]
- f[j] += (f[u] + w[i] * g[u]) / out[u];
- g[j] += g[u] / out[u]; // p[j]也需要概率累加
- //拓扑序的标准套路
- in[j]--;
- if (!in[j]) q.push(j);
- }
- }
-}
-
-int main() {
- //初始化邻接表
- memset(h, -1, sizeof h);
- cin >> n >> m;
-
- while (m--) {
- int a, b, c;
- cin >> a >> b >> c;
- add(a, b, c);
- //维护出度,入度
- out[a]++, in[b]++;
- }
- //拓扑序
- topsort();
-
- //正向递推,输出结果,保留两位小数
- printf("%.2lf", f[n]);
-
- return 0;
-}
-```
-### 三、倒推法
-现在学会了正推,来看看 **逆推**,即 **从终点找到起点**
-
-
-
-
-设 $f[x]$ 表示结点 $x$ 走到终点所经过的路径的期望长度。显然 $f[n]=0$ ,最后要求 $f[1]$ 。
-
-一般来说,**初始状态确定时可用顺推,终止状态确定时可用逆推**。
-
-设 $x$ 出发有 $k$ 条边,分别到达 $y_1,y_2...y_k$ ,边长分别为 $z_1,z_2...z_k$ ,根据数学期望的定义和性质,有:
-
-$$f[x]=\frac 1 k\times (f[y_1]+z_1)+\frac 1 k\times (f[y_2]+z_2)+...+\frac 1 k\times (f[y_k]+z_k)=\frac 1 k \times \sum_{i=1}^k(f[y_i]+z_i)$$
-根据设定已经确定是能够到达 $n$ 点了,概率为 $1$ 。
-
-$f[n]$ 已知,需要求解 $f[1]$ ,建立 **反向图**,按照 **拓扑序** 求解。
-
-#### 倒推代码
-```cpp {.line-numbers}
-#include
-using namespace std;
-const int N = 100010, M = N << 1;
-int n, m;
-int in[N], g[N]; //入度,入度的备份数组,原因:in在topsort中会不断变小受破坏
-
-double f[N];
-
-//链式前向星
-int e[M], h[N], idx, w[M], ne[M];
-void add(int a, int b, int c = 0) {
- e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
-}
-
-void topsort() {
- queue q;
- q.push(n);
- f[n] = 0; // n到n的距离期望是0
- while (q.size()) {
- int u = q.front();
- q.pop();
- for (int i = h[u]; ~i; i = ne[i]) { //枚举每条入边(因为是反向图)
- int j = e[i];
- f[j] += (f[u] + w[i]) / g[j];
- in[j]--;
- if (in[j] == 0) q.push(j);
- }
- }
-}
-int main() {
- memset(h, -1, sizeof(h));
- cin >> n >> m;
-
- while (m--) {
- int a, b, c;
- cin >> a >> b >> c;
- add(b, a, c); //反向图,计算从n到1
- in[a]++; //入度
- g[a] = in[a]; //入度数量
- }
- topsort();
- printf("%.2lf\n", f[1]);
- return 0;
-}
-```
\ No newline at end of file
diff --git a/TangDou/AcWing/Math/QiWang/217_DaoTui.cpp b/TangDou/AcWing/Math/QiWang/217_DaoTui.cpp
deleted file mode 100644
index ba0fe13..0000000
--- a/TangDou/AcWing/Math/QiWang/217_DaoTui.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include
-using namespace std;
-const int N = 100010, M = N << 1;
-int n, m;
-int in[N], g[N]; //入度,入度的备份数组,原因:in在topsort中会不断变小受破坏
-
-double f[N];
-
-//链式前向星
-int e[M], h[N], idx, w[M], ne[M];
-void add(int a, int b, int c = 0) {
- e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
-}
-
-void topsort() {
- queue q;
- q.push(n);
- f[n] = 0; // n到n的距离期望是0
- while (q.size()) {
- int u = q.front();
- q.pop();
- for (int i = h[u]; ~i; i = ne[i]) { //枚举每条入边(因为是反向图)
- int j = e[i];
- f[j] += (f[u] + w[i]) / g[j];
- in[j]--;
- if (in[j] == 0) q.push(j);
- }
- }
-}
-int main() {
- memset(h, -1, sizeof(h));
- cin >> n >> m;
-
- while (m--) {
- int a, b, c;
- cin >> a >> b >> c;
- add(b, a, c); //反向图,计算从n到1
- in[a]++; //入度
- g[a] = in[a]; //入度数量
- }
- topsort();
- printf("%.2lf\n", f[1]);
- return 0;
-}
\ No newline at end of file
diff --git a/TangDou/AcWing/Math/QiWang/217_ZhengTui.cpp b/TangDou/AcWing/Math/QiWang/217_ZhengTui.cpp
deleted file mode 100644
index 05e64ee..0000000
--- a/TangDou/AcWing/Math/QiWang/217_ZhengTui.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#include
-using namespace std;
-const int N = 1e5 + 10, M = 2 * N;
-
-//邻接表
-int h[N], e[M], ne[M], w[M], idx;
-void add(int a, int b, int c) {
- e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
-}
-
-int n, m; // n个顶点,m条边
-
-int out[N], in[N]; //出度,入度
-double f[N], g[N]; // f:数学期望结果 g:概率
-
-void topsort() {
- queue q;
- //起点为1,起点的概率为100%
- q.push(1);
- g[1] = 1.0;
- f[1] = 0.0;
-
- // DAG,执行拓扑序,以保证计算的顺序正确,确保递归过程中,前序数据都已处理完毕
- while (q.size()) {
- auto u = q.front();
- q.pop();
-
- for (int i = h[u]; ~i; i = ne[i]) { //枚举的是每边相邻边
- int j = e[i]; //此边,一端是t,另一端是j
- //此边边条w[i]
- f[j] += (f[u] + w[i] * g[u]) / out[u];
- g[j] += g[u] / out[u]; // p[j]也需要概率累加
- //拓扑序的标准套路
- in[j]--;
- if (!in[j]) q.push(j);
- }
- }
-}
-
-int main() {
- //初始化邻接表
- memset(h, -1, sizeof h);
- cin >> n >> m;
-
- while (m--) {
- int a, b, c;
- cin >> a >> b >> c;
- add(a, b, c);
- //维护出度,入度
- out[a]++, in[b]++;
- }
- //拓扑序
- topsort();
-
- //正向递推,输出结果,保留两位小数
- printf("%.2lf", f[n]);
-
- return 0;
-}
\ No newline at end of file
diff --git a/TangDou/AcWing/Math/QiWang/218.md b/TangDou/AcWing/Math/QiWang/218.md
deleted file mode 100644
index a4c716a..0000000
--- a/TangDou/AcWing/Math/QiWang/218.md
+++ /dev/null
@@ -1,152 +0,0 @@
-##[$AcWing$ $218$. 扑克牌 ](https://www.acwing.com/problem/content/description/220/)
-
-### 一、题目描述
-$Admin$ 生日那天,$Rainbow$ 来找 $Admin$ 玩扑克牌。
-
-玩着玩着 $Rainbow$ 觉得太没意思了,于是决定给 $Admin$ 一个考验。
-
-$Rainbow$ 把一副扑克牌($54$张)随机洗开,倒扣着放成一摞。
-
-然后 $Admin$ 从上往下依次翻开每张牌,每翻开一张黑桃、红桃、梅花或者方块,就把它放到对应花色的堆里去。
-
-$Rainbow$ 想问问 $Admin$,得到 $A$ 张黑桃、$B$ 张红桃、$C$ 张梅花、$D$ 张方块需要翻开的牌的张数的期望值 $E$ 是多少?
-
-特殊地,如果翻开的牌是大王或者小王,$Admin$ 将会把它作为某种花色的牌放入对应堆中,使得放入之后 $E$的值尽可能小。
-
-由于 $Admin$ 和 $Rainbow$ 还在玩扑克,所以这个程序就交给你来写了。
-
-**输入格式**
-输入仅由一行,包含四个用空格隔开的整数,$A,B,C,D$。
-
-**输出格式**
-输出需要翻开的牌数的期望值 $E$,四舍五入保留 $3$ 位小数。
-
-如果不可能达到输入的状态,输出 `-1.000`。
-
-**数据范围**
-$0≤A,B,C,D≤15$
-
-**输入样例:**
-```cpp {.line-numbers}
-1 2 3 4
-```
-
-**输出样例:**
-```cpp {.line-numbers}
-16.393
-```
-
-### 二、题意分析
-
-$Q$:为什么从终止状态向起始状态递推?
-
-**答**:满足条件的终止状态较多,而起始状态唯一。考虑以终止状态为初值,起始状态为目标,进行动态规划。
-
-#### 状态表示
-$f[a][b][c][d][x][y]$ : 当前已翻开状态下,还需翻开牌的数量 **期望数**。
-
-- $a,b,c,d$ 为已翻开的各类牌 (黑红花片) 的数量
-- $x,y$代表大、小王的状态($0$为未翻开,$1$代表已翻开且当做黑桃,以此类推), 设 $rst$ 为剩余牌的数量。
-$$rst=54-a-b-c-d-(x!=0)-(y!=0)$$
-
-若 $a < 13$,则当前抽到黑桃的贡献为
-
-$$\frac{13−a}{rst} \times f[a+1][b][c][d][x][y]$$
-
-其余花色同理。若小王被抽取,取可转移状态期望最小的一个进行状态转移,其贡献为:
-
-$$\frac{1}{rst} \times \min_{1≤i≤4}f[a][b][c][d][i][y]$$
-
-大王同理。
-
-记忆化搜索求解,若无牌可抽仍未到达 $a > = A \&\& b > = B \&\& c > = C \&\& d > = D$ 的终止状态,则期望为正无穷,代表不合法的状态。
-
-
-#### 三、实现代码
-
-```cpp {.line-numbers}
-#include
-using namespace std;
-const int N = 15;
-const int INF = 0x3f3f3f3f;
-double f[N][N][N][N][5][5];
-int st[N][N][N][N][5][5];
-int A, B, C, D;
-
-//如果大小王翻出来放1里,则a++,放2里b++,...
-void add(int &a, int &b, int &c, int &d, int x) {
- if (x == 1) a++;
- if (x == 2) b++;
- if (x == 3) c++;
- if (x == 4) d++;
-}
-
-/*
-功能:计算当前状态f(a,b,c,d,x,y)下的期望值
-*/
-double dfs(int a, int b, int c, int d, int x, int y) {
- //记忆化,同时因为f为double类型,不能使用传统的memset(0x3f)之类
- //进行初始化并判断是否修改过,只能再开一个st数组
- if (st[a][b][c][d][x][y]) return f[a][b][c][d][x][y];
- st[a][b][c][d][x][y] = 1;
-
- //递归出口:当前状态是否到达目标状态,目标状态的期望值是0
- int ta = a, tb = b, tc = c, td = d; //抄出来
- add(ta, tb, tc, td, x), add(ta, tb, tc, td, y); //大王小王会改变四个花色的数量
- if (ta >= A && tb >= B && tc >= C && td >= D) return 0;
-
- //当前状态下的剩余牌数量
- int rst = 54 - ta - tb - tc - td;
- if (rst == 0) return INF; //还没有完成目标,没有剩余的牌了,无解
-
- //当前状态可以向哪些状态转移
- // Q:v为什么要初始化为1?
- // A:看题解内容
- double v = 1;
- if (a < 13) //黑桃有剩余,可能选出的是黑桃
- v += dfs(a + 1, b, c, d, x, y) * (13 - a) / rst;
- if (b < 13) //红桃有剩余,可能选出的是红桃
- v += dfs(a, b + 1, c, d, x, y) * (13 - b) / rst;
- if (c < 13) //梅花有剩余,可能选出的是梅花
- v += dfs(a, b, c + 1, d, x, y) * (13 - c) / rst;
- if (d < 13) //方块有剩余,可能选出的是方块
- v += dfs(a, b, c, d + 1, x, y) * (13 - d) / rst;
-
- //如果小王没有被选出
- if (x == 0)
- v += min(min(dfs(a, b, c, d, 1, y), dfs(a, b, c, d, 2, y)), min(dfs(a, b, c, d, 3, y), dfs(a, b, c, d, 4, y))) / rst;
-
- //如果大王没有被选出
- if (y == 0)
- v += min(min(dfs(a, b, c, d, x, 1), dfs(a, b, c, d, x, 2)), min(dfs(a, b, c, d, x, 3), dfs(a, b, c, d, x, 4))) / rst;
-
- return f[a][b][c][d][x][y] = v;
-}
-
-int main() {
- cin >> A >> B >> C >> D;
- //① 终点状态不唯一,起点是唯的的,所以以起点为终点,以终点为起点,反着推
- //② AcWing 217. 绿豆蛙的归宿 需要建图,本题不用建图
- double res = dfs(0, 0, 0, 0, 0, 0); //四种花色、大小王都还没有被抽取
-
- if (res > INF / 2) //因为是浮点数,不能用等号判断是不是相等,简单的办法就是INF/2
- puts("-1.000");
- else
- printf("%.3f\n", res);
- return 0;
-}
-```
-
-### 四、期望值为什么初始化为$1$?
-
-$f[i]$: 从$i$卡牌状态到终点状态所需要的**期望卡牌数**
-
-每次抽一张牌变到下个状态,所以每条路径的权值为$1$
-
-$$\large f[v]=p_1×(f[1]+1)+p_2×(f[2]+1)+p_3×(f[3]+1)+…+p_k×(f[k]+1) = \\
-\sum_{i=1}^{k}p_i+\sum_{i=1}^{k}p_i \times f[i]
-$$
-
- 因为$v$一定能到达下个局面,所以下个状态的概率和为$1$,这里的$\large \displaystyle \sum_{i=1}^{k}p_i=1$ 那么就有:$\displaystyle \large f[v]=1+\sum_{i=1}^{k}p_i \times f[i]$
-综上这里的$f[v]$可以初始化为$1$!
-
\ No newline at end of file
diff --git a/TangDou/AcWing/Math/QiWang/218_dp.cpp b/TangDou/AcWing/Math/QiWang/218_dp.cpp
deleted file mode 100644
index ca614d3..0000000
--- a/TangDou/AcWing/Math/QiWang/218_dp.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#include
-using namespace std;
-const int INF = 0x3f3f3f3f;
-const int N = 15;
-double f[N][N][N][N][5][5];
-int a, b, c, d;
-int main() {
- memset(f, -1, sizeof f);
- cin >> a >> b >> c >> d;
-
- for (int i = 13; i >= 0; i--)
- for (int j = 13; j >= 0; j--)
- for (int k = 13; k >= 0; k--)
- for (int w = 13; w >= 0; w--)
- for (int x = 4; x >= 0; x--)
- for (int y = 4; y >= 0; y--) {
- double &v = f[i][j][k][w][x][y];
- if (i + (x == 1) + (y == 1) >= a && j + (x == 2) + (y == 2) >= b
- && k + (x == 3) + (y == 3) >= c && w + (x == 4) + (y == 4) >= d) {
- v = 0;
- continue;
- }
-
- v = 1;
- int sum = i + j + k + w + (x != 0) + (y != 0);
- if (i < 13) v += f[i + 1][j][k][w][x][y] * (13 - i) / (54 - sum);
- if (j < 13) v += f[i][j + 1][k][w][x][y] * (13 - j) / (54 - sum);
- if (k < 13) v += f[i][j][k + 1][w][x][y] * (13 - k) / (54 - sum);
- if (w < 13) v += f[i][j][k][w + 1][x][y] * (13 - w) / (54 - sum);
- if (x == 0) {
- double t = INF;
- for (int u = 1; u <= 4; u++) t = min(t, f[i][j][k][w][u][y] / (54 - sum));
- v += t;
- }
- if (y == 0) {
- double t = INF;
- for (int u = 1; u <= 4; u++) t = min(t, f[i][j][k][w][x][u] / (54 - sum));
- v += t;
- }
- }
-
- if (f[0][0][0][0][0][0] > 54)
- printf("-1.000");
- else
- printf("%.3lf", f[0][0][0][0][0][0]);
-
- return 0;
-}
\ No newline at end of file
diff --git a/TangDou/AcWing/Math/QiWang/218_dfs.cpp b/TangDou/AcWing_TiGao/T5/QiWang/218.cpp
similarity index 100%
rename from TangDou/AcWing/Math/QiWang/218_dfs.cpp
rename to TangDou/AcWing_TiGao/T5/QiWang/218.cpp
diff --git a/TangDou/AcWing_TiGao/T5/QiWang/218_dfs.cpp b/TangDou/AcWing_TiGao/T5/QiWang/218_dfs.cpp
deleted file mode 100644
index cb9302e..0000000
--- a/TangDou/AcWing_TiGao/T5/QiWang/218_dfs.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-#include
-using namespace std;
-const int N = 15;
-const int INF = 0x3f3f3f3f;
-double f[N][N][N][N][5][5];
-int st[N][N][N][N][5][5];
-int A, B, C, D;
-
-//如果大小王翻出来放1里,则a++,放2里b++,...
-void add(int &a, int &b, int &c, int &d, int x) {
- if (x == 1) a++;
- if (x == 2) b++;
- if (x == 3) c++;
- if (x == 4) d++;
-}
-
-/*
-功能:计算当前状态f(a,b,c,d,x,y)下的期望值
-*/
-double dfs(int a, int b, int c, int d, int x, int y) {
- //记忆化,同时因为f为double类型,不能使用传统的memset(0x3f)之类
- //进行初始化并判断是否修改过,只能再开一个st数组
- if (st[a][b][c][d][x][y]) return f[a][b][c][d][x][y];
- st[a][b][c][d][x][y] = 1;
-
- //递归出口:当前状态是否到达目标状态,目标状态的期望值是0
- int ta = a, tb = b, tc = c, td = d; //抄出来
- add(ta, tb, tc, td, x), add(ta, tb, tc, td, y); //大王小王会改变四个花色的数量
- if (ta >= A && tb >= B && tc >= C && td >= D) return 0;
-
- //当前状态下的剩余牌数量
- int rst = 54 - ta - tb - tc - td;
- if (rst == 0) return INF; //还没有完成目标,没有剩余的牌了,无解
-
- //当前状态可以向哪些状态转移
- // Q:v为什么要初始化为1?
- // A:看题解内容
- double v = 1;
- if (a < 13) //黑桃有剩余,可能选出的是黑桃
- v += dfs(a + 1, b, c, d, x, y) * (13 - a) / rst;
- if (b < 13) //红桃有剩余,可能选出的是红桃
- v += dfs(a, b + 1, c, d, x, y) * (13 - b) / rst;
- if (c < 13) //梅花有剩余,可能选出的是梅花
- v += dfs(a, b, c + 1, d, x, y) * (13 - c) / rst;
- if (d < 13) //方块有剩余,可能选出的是方块
- v += dfs(a, b, c, d + 1, x, y) * (13 - d) / rst;
-
- //如果小王没有被选出
- if (x == 0)
- v += min(min(dfs(a, b, c, d, 1, y), dfs(a, b, c, d, 2, y)), min(dfs(a, b, c, d, 3, y), dfs(a, b, c, d, 4, y))) / rst;
-
- //如果大王没有被选出
- if (y == 0)
- v += min(min(dfs(a, b, c, d, x, 1), dfs(a, b, c, d, x, 2)), min(dfs(a, b, c, d, x, 3), dfs(a, b, c, d, x, 4))) / rst;
-
- return f[a][b][c][d][x][y] = v;
-}
-
-int main() {
- cin >> A >> B >> C >> D;
- //① 终点状态不唯一,起点是唯的的,所以以起点为终点,以终点为起点,反着推
- //② AcWing 217. 绿豆蛙的归宿 需要建图,本题不用建图
- double res = dfs(0, 0, 0, 0, 0, 0); //四种花色、大小王都还没有被抽取
-
- if (res > INF / 2) //因为是浮点数,不能用等号判断是不是相等,简单的办法就是INF/2
- puts("-1.000");
- else
- printf("%.3f\n", res);
- return 0;
-}
\ No newline at end of file
diff --git a/TangDou/AcWing_TiGao/T5/QiWang/218_dp.cpp b/TangDou/AcWing_TiGao/T5/QiWang/218_dp.cpp
deleted file mode 100644
index ca614d3..0000000
--- a/TangDou/AcWing_TiGao/T5/QiWang/218_dp.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#include
-using namespace std;
-const int INF = 0x3f3f3f3f;
-const int N = 15;
-double f[N][N][N][N][5][5];
-int a, b, c, d;
-int main() {
- memset(f, -1, sizeof f);
- cin >> a >> b >> c >> d;
-
- for (int i = 13; i >= 0; i--)
- for (int j = 13; j >= 0; j--)
- for (int k = 13; k >= 0; k--)
- for (int w = 13; w >= 0; w--)
- for (int x = 4; x >= 0; x--)
- for (int y = 4; y >= 0; y--) {
- double &v = f[i][j][k][w][x][y];
- if (i + (x == 1) + (y == 1) >= a && j + (x == 2) + (y == 2) >= b
- && k + (x == 3) + (y == 3) >= c && w + (x == 4) + (y == 4) >= d) {
- v = 0;
- continue;
- }
-
- v = 1;
- int sum = i + j + k + w + (x != 0) + (y != 0);
- if (i < 13) v += f[i + 1][j][k][w][x][y] * (13 - i) / (54 - sum);
- if (j < 13) v += f[i][j + 1][k][w][x][y] * (13 - j) / (54 - sum);
- if (k < 13) v += f[i][j][k + 1][w][x][y] * (13 - k) / (54 - sum);
- if (w < 13) v += f[i][j][k][w + 1][x][y] * (13 - w) / (54 - sum);
- if (x == 0) {
- double t = INF;
- for (int u = 1; u <= 4; u++) t = min(t, f[i][j][k][w][u][y] / (54 - sum));
- v += t;
- }
- if (y == 0) {
- double t = INF;
- for (int u = 1; u <= 4; u++) t = min(t, f[i][j][k][w][x][u] / (54 - sum));
- v += t;
- }
- }
-
- if (f[0][0][0][0][0][0] > 54)
- printf("-1.000");
- else
- printf("%.3lf", f[0][0][0][0][0][0]);
-
- return 0;
-}
\ No newline at end of file