题目描述
传送门
题意:
一个人粉刷n*n的墙,每一次随机选择一个格子染色,每一行和每一列都至少染了一个的时候结束,每染一个花费1的时间。求结束时间的期望。
题解
令f(i,j)表示染了i行,j列到结束的期望
转移方程很显然
f(i,j)=(i/n)* (j/n) * (f(i,j)+1)+(i/n) * (1-j/n) * (f(i,j+1)+1)+(1-i/n) * (j/n) * (f(i+1,j)+1)+(1-i/n) * (1-j/n) * (f(i+1,j+1)+1)
移项化简即可
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 2005
int n,m,x,y,hang[N],lie[N];
double f[N][N];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
scanf("%d%d",&x,&y);
hang[x]=1,lie[y]=1;
}
x=0,y=0;for (int i=1;i<=n;++i) x+=hang[i],y+=lie[i];
for (int i=n;i>=0;--i)
for (int j=n;j>=0;--j)
{
if (i==n&&j==n) continue;
double I=(double)i/(double)n,J=(double)j/(double)n;
f[i][j]+=(f[i][j+1]+1.0)*I*(1.0-J);
f[i][j]+=(f[i+1][j]+1.0)*(1.0-I)*J;
f[i][j]+=(f[i+1][j+1]+1.0)*(1.0-I)*(1.0-J);
f[i][j]+=I*J;
f[i][j]/=(1.0-I*J);
}
printf("%.10lf\n",f[x][y]);
}