zoj 3822 (2014 牡丹江区域赛 D) Domination

本文探讨了一个关于在n*m棋盘上随机放置棋子直至每行每列至少有一个棋子的问题,并通过概率动态规划的方法给出了求解该过程中天数期望的算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        题意:一个n*m的棋盘,每天等概率随机在一个空位上放一个棋子,直到每行每列都至少有一个棋子。问这个过程持续天数的期望。

        思路:概率dp。如果想到了如何表示状态,剩下的就不难了。dp(i,j,k)表示出现 i行中有棋子,j列中有棋子,一共有k个棋子 这种情况的概率。其中i=0~n,j=0~m,k=0~n*m-min(n,m)+1。初态是dp(0,0,0)=1.0。状态转移有4种情况,即放下棋子后没有新增的行列,仅增加行,仅增加列,同时增加行列,具体状态转移见代码。最后按照期望的定义算一下即可。


#include <iostream>       
#include <stdio.h>       
#include <cmath>       
#include <algorithm>       
#include <iomanip>       
#include <cstdlib>       
#include <string>       
#include <memory.h>       
#include <vector>       
#include <queue>       
#include <stack>       
#include <map>     
#include <set>     
#include <ctype.h>       
#include <sstream>   
#define INF 1000000000   
#define ll long long   
#define min3(a,b,c) min(a,min(b,c))   
#define max3(a,b,c) max(a,max(b,c))   
#define MAXN 100010   
     
using namespace std;     

double dp[52][52][2510];

int main(){
	int n,m;
	int t; cin>>t;
	while(t--){
		cin>>n>>m;
		//init
		for(int k=0;k<=n*m;k++){
			for(int i=0;i<=n;i++){
				for(int j=0;j<=m;j++){
					dp[i][j][k]=0.0;
				}
			}
		}
		dp[0][0][0]=1.0;
		//
		double ans=0.0;
		int end=n*m-min(n,m)+1;
		for(int k=0;k<=end;k++){
			for(int i=0;i<n;i++){
				for(int j=0;j<m;j++){
					dp[i+1][j+1][k+1]+=dp[i][j][k]*(n*m-i*m-j*n+i*j)/(n*m-k);
					dp[i+1][j+1][k+1]+=dp[i][j+1][k]*( (n-i)*(j+1) )/(n*m-k);
					dp[i+1][j+1][k+1]+=dp[i+1][j][k]*( (m-j)*(i+1) )/(n*m-k);
					if(!(i+1==n&&j+1==m))dp[i+1][j+1][k+1]+=dp[i+1][j+1][k]*((i+1)*(j+1)-k)/(n*m-k);
					else ans+=dp[n][m][k]*k;
				}
			}
		}
		
		printf("%.10lf\n",ans);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值