ACM-ICPC 2018 徐州赛区网络预赛 C. Cacti Lottery
标签
- 概率&期望
- 期望的期望
前言
- 这题我花了8个小时…第一次接触期望的题…太菜了…
简明题意
- 有一个3*3的棋盘,你在和Morgana游戏。棋盘中每个格子都有一个数,但,有些格子的数你们都知道,有些格子的数字只有Morgana知道,还有一些数你和Morgana都不知道。游戏开始时,Morgana会选取一横行或一竖行或一斜行的和,在表中找到对应的值作为自己的分数。问最终,你预测Morgana期望得分是多少
思路
- 首先我们要明白,“我”预测Morgana的期望得分和Morgana自己预测自己的期望得分得到的结果是不一样的。如果是Morgana预测自己的得分,那么他不知道的只有#部分,所以计算出每一种#的选择方法的贡献就可以了,至于*的那部分,Morgana是知道的,所以如果是Morgana去预测,但又不告诉 * 是什么,Morgana就没法预测。所以这个题目让我们去预测Morgana的期望得分。
- 对于Morgana自己,他知道 * 的部分是多少,他不知道#的部分是多少,也就是说 # 是变化的,因此,要对每一种 # 排列求一次贡献,就可以算出来,Morgana自己的期望得分
- 现在不是让你算Morgana自己的期望得分,而是你去算Morgana的得分。现在的主体是你,对于你作为主体,* 的变化的,所以你应该去计算每一种 * 排列的贡献
- 这题就是 期望的期望
- 我可能说的也不是很清楚,以后再多刷一些概率&期望的题,再来把!
注意事项
- 无
总结
- 期望的期望~~ 注意主体,主体换了,计算谁的贡献也就变了
AC代码
- 代码写的非常丑…凑合一下吧
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int frac(int n)
{
int cnt = 1;
for (int i = 1; i <= n; i++)
cnt *= i;
return cnt;
}
int A(int m, int n)
{
return frac(n) / frac(n - m);
}
int cnt1, cnt2;
char g[4][4];
bool used[10];
double w[25] = { 0,0,0,0,0,0,10000,36,720,360,80,252,108,72,54,180,72,180,119,36,360,1080,144,1800,3600 };
double ans[10];
void dfs2(int x, int y)
{
if (x == 4)
{
ans[1] += w[g[1][1] + g[1][2] + g[1][3] - 3 * '0'];
ans[2] += w[g[2][1] + g[2][2] + g[2][3] - 3 * '0'];
ans[3] += w[g[3][1] + g[3][2] + g[3][3] - 3 * '0'];
ans[4] += w[g[1][1] + g[2][1] + g[3][1] - 3 * '0'];
ans[5] += w[g[1][2] + g[2][2] + g[3][2] - 3 * '0'];
ans[6] += w[g[1][3] + g[2][3] + g[3][3] - 3 * '0'];
ans[7] += w[g[1][1] + g[2][2] + g[3][3] - 3 * '0'];
ans[8] += w[g[1][3] + g[2][2] + g[3][1] - 3 * '0'];
return;
}
if (g[x][y] == '#')
{
for (int i = 1; i <= 9; i++)
if (!used[i])
{
used[i] = 1;
g[x][y] = i + '0';
if (y + 1 <= 3)
dfs2(x, y + 1);
else
dfs2(x + 1, 1);
g[x][y] = '#';
used[i] = 0;
}
return;
}
if (y + 1 <= 3)
dfs2(x, y + 1);
else
dfs2(x + 1, 1);
}
double ans0;
void dfs(int x, int y)
{
if (x == 4)
{
memset(ans, 0, sizeof ans);
dfs2(1, 1);
double cur = 0;
for (int i = 1; i <= 8; i++)
cur = max(cur, ans[i]);
ans0 += cur ;
return;
}
if (g[x][y] == '*')
{
for (int i = 1; i <= 9; i++)
if (!used[i])
{
used[i] = 1;
g[x][y] = i + '0';
if (y + 1 <= 3)
dfs(x, y + 1);
else
dfs(x + 1, 1);
g[x][y] = '*';
used[i] = 0;
}
return;
}
if (y + 1 <= 3)
dfs(x, y + 1);
else
dfs(x + 1, 1);
}
void solve()
{
int t;
scanf("%d", &t);
while (t--)
{
cnt1 = 0, cnt2 = 0;
memset(used, 0, sizeof used);
for (int i = 1; i <= 3; i++)
scanf("%s", g[i] + 1);
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
{
if (g[i][j] >= '1' && g[i][j] <= '9')
used[g[i][j] - '0'] = 1;
if (g[i][j] == '#') cnt1++;
if (g[i][j] == '*') cnt2++;
}
dfs(1, 1);
printf("%.8lf\n", ans0 / A(cnt2, cnt1 + cnt2) / A(cnt1, cnt1));
//printf("%.8lf\n", sum / A(cnt2, cnt1 + cnt2) / A(cnt1, cnt1));
ans0 = 0;
}
}
int main()
{
//freopen("Testin.txt", "r", stdin);
solve();
return 0;
}