ACM-ICPC 2018 徐州赛区网络预赛 概率&期望+期望的期望


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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值