【XSY1594】棋盘控制 概率DP

题目描述

  给你一个(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;
}
原文地址:https://www.cnblogs.com/ywwyww/p/8511350.html