zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    4500 小Q系列故事——屌丝的逆袭
    HDU 1171 Big Event in HDU
    linux库文件 /usr/lib
    HDU 1860 统计字符
    编程之美~~传话游戏
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1203 I NEED A OFFER!
    各种树
    HDU 3127 WHUgirls
    01背包 完全背包 多重背包 二维费用背包
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8511350.html
Copyright © 2011-2022 走看看