ICPC-概率DP-ZOJ3822

对N*M的棋盘,问满足行至少一个棋子,列至少一个棋子的步数概率。
对每个状态:来自四个不同状态
位置是固定的,所以不能在一个位置上多次,于是我们至少需要3维dp

而且50*50相当小

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const ll mod=998244353;
const int maxn=2500;
double dp[55][55][maxn+5];//用i行,j列,使用k步   离结束还需要的期望天数
int main(){
    int n,m,t;
	scanf("%d",&t);
	while(t--){
       scanf("%d %d",&n,&m);
       mem(dp,0); //最后的n,m,k(任意多)时候,离结束的天数是0天(dp[n][m][maxn+5])
       for(int i=n;i>=0;i--){
          for(int j=m;j>=0;j--){
            if(i==n&&j==m)continue;
            for(int k=i*j;k>=min(i,j);k--){//空行(n-i)  空列(m-j)   走k步时(限定在i*j步里,限定必须至少(min(i,j)))
                //总区域i*j>=k才符合实际条件
                //概率就是   (满足什么条件我需要走的总方案) / (当前我可以走的所有方案)
                if(i*j>=k+1)dp[i][j][k]+=(1+dp[i][j][k+1])*((double)(i*j-k)/(double)(n*m-k));//从i,j,k到i,j,k+1的转移
                if((i+1)*j>=k+1)dp[i][j][k]+=(1+dp[i+1][j][k+1])*((double)((n-i)*j)/(double)(n*m-k));//i,j,k->i+1,j,k+1
                if((j+1)*i>=k+1)dp[i][j][k]+=(1+dp[i][j+1][k+1])*((double)((m-j)*i)/(double)(n*m-k));//i,j,k->i,j+1,k+1
                if((i+1)*(j+1)>=k+1)dp[i][j][k]+=(1+dp[i+1][j+1][k+1])*((double)((n-i)*(m-j))/(double)(n*m-k));//i,j,k->i+1,j+1,k+1
            }
          }
       }
       printf("%.9f\n",dp[0][0][0]);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值