Red is Good

题目大意:桌面上有 R 张红牌和 B 张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到 1 美元,黑牌则付出 1 美元。可以随时停止翻牌,在最优策略下平均能得到多少钱。
考虑期望Dp
\(f[a][b]\)表示有a张红牌,b张黑牌时的期望钱数
容易得到\(f[a][0]=a\)
\(f[a][b]\)可以从两个状态转移过来,即\(f[a-1][b]\)\(f[a][b-1]\)
\(f[a-1][b]\)的概率为\(\frac{a}{a+b}\),转移过来期望加1
\(f[a][b-1]\)的概率为\(\frac{b}{a+b}\),转移过来期望减1
然后就可以得到\(f[a][b]=(f[a-1][b]+1)\times \frac{a}{a+b}+(f[a][b-1]-1)\times \frac{b}{a+b}\)
但是在\(b>a\)时,\(f[a][b]\)是负数,它真的是负数吗?
不是,因为根据最优策略\(f[a][b]\)可以等于0
所以\(f[a][b]=max(0,(f[a-1][b]+1)\times \frac{a}{a+b}+(f[a][b-1]-1)\times \frac{b}{a+b})\)

#include<bits/stdc++.h>
using namespace std;
inline int read() {
	int s=1,a=0;
	char c=getchar();
	while(!isdigit(c)) {
		if(c=='-') s=-s;
		c=getchar();
	}
	while(isdigit(c)) {
		a=a*10+c-'0';
		c=getchar();
	}
	return s*a;
}
const int N=5e3+8;
int r,b;
double f[2][N];
int main() {
	r=read(),b=read();
	for(int i=1;i<=r;i++) {
		f[i&1][0]=i*1.0000000;
		for(int j=1;j<=b;j++) {
			f[i&1][j]=max(0.0000000,(f[i&1^1][j]+1)*((i*1.0000000)/(i+j)*1.0000000)+(f[i&1][j-1]-1)*((j*1.0000000)/(i+j)*1.0000000));
		}
	}
	f[r&1][b]-=0.0000005;
	printf("%.6f\n",f[r&1][b]);
	return 0;
}
posted @ 2021-07-02 13:16  redproblemdog  阅读(58)  评论(0编辑  收藏  举报