题目描述
给你一个(n imes m)的棋盘,每次随机在棋盘上放一个国际象棋中的车,不能和以前放的重叠。每个车可以控制当前行和当前列。当所有行和所有列都被控制时结束游戏。问你结束时期望放了多少个车。
注意:结束的条件是所有行和所有列都被控制,而不是所有格子都被控制。
(n,mleq 50)
题解
简单DP
(f_{i,j,k})表示放了(k)个车后控制了(i)行(j)列的概率
[f_{i,j,k}=frac{f_{i,j,k-1} imes(ij-(k-1))+f_{i,j-1,k-1} imes i(m-j+1)+f_{i-1,j,k-1} imes j(n-i+1)+f_{i-1,j-1,k-1} imes(n-i+1)(m-j+1)}{nm-k+1}
]
答案是
[sum_{i=1}^{nm}i(f_{n,m,i}-f_{n,m,i-1})
]
弄个滚动数组搞一下
时间复杂度:(O(n^4))
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
double f[2][60][60];
void solve()
{
double ans=0;
int n,m;
scanf("%d%d",&n,&m);
memset(f,0,sizeof f);
int i,j,k;
f[0][0][0]=1;
int t=0;
for(k=1;k<=n*m;k++)
{
t^=1;
double now=1./(n*m-k+1);
memset(f[t],0,sizeof f[t]);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
f[t][i][j]=(f[t^1][i][j]*(i*j-k+1)+f[t^1][i-1][j]*(n-i+1)*j+f[t^1][i][j-1]*i*(m-j+1)+f[t^1][i-1][j-1]*(n-i+1)*(m-j+1))*now;
ans+=k*(f[t][n][m]-f[t^1][n][m]);
}
printf("%.10lf
",ans);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
solve();
return 0;
}