zoj3822 Domination 概率dp --- 2014 ACM-ICPC Asia Mudanjiang Regional Contest

3 篇文章 0 订阅

一个n行m列的棋盘,每次可以放一个棋子,问要使得棋盘的每行每列都至少有一个棋子 需要的放棋子次数的期望。

dp[i][j][k]表示用了k个棋子共能占领棋盘的i行j列的概率。

那么对于每一颗棋子,在现有的棋盘上,它可能有四种影响:新占了一行,新占了一列,既占了新的一行又占了新的一列,无影响。

对于每一种情况,dp[i][j][k]=原始状态的概率×选到这样的位置的概率

最后算答案的时候注意到,题目问的是到第k个刚好放完n行m列,也就是最后一个棋子一定是有作用的,

所以用dp[i][j][k]-dp[i][j][k-1]得到是第k个棋子恰好使得每行每列都占领的概率。


#include<cstdio>
#include<cstring>
double dp[55][55][2550];
int n,m;
int main()
{
    int T,i,j,k;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        int sum=n*m;
        for(i=0;i<=n;i++)
            for(j=0;j<=m;j++)
                for(k=0;k<=sum;k++) dp[i][j][k]=0;
        dp[0][0][0]=1.0;
        for(k=1;k<=sum;k++)
            for(i=1;i<=n;i++)
                for(j=1;j<=m;j++)
                {
                    dp[i][j][k]+=(dp[i][j][k-1]*(i*j-k+1)*1.0/(sum-k+1));//添加的位置没有新增新行或新列
                    dp[i][j][k]+=(dp[i-1][j][k-1]*((n-i+1)*j)*1.0/(sum-k+1));//增加行不增加列
                    dp[i][j][k]+=(dp[i][j-1][k-1]*(m-j+1)*i*1.0/(sum-k+1));//增加列不增加行
                    dp[i][j][k]+=(dp[i-1][j-1][k-1]*(n-i+1)*(m-j+1)*1.0/(sum-k+1));//既增加列也增加行
                 //   printf("i:%d j;%d k;%d dp:%lf\n",i,j,k,dp[i][j][k]);
                }
        double ans=0;
        for(k=1;k<=sum;k++) ans+=(dp[n][m][k]-dp[n][m][k-1])*k;
        printf("%.10lf\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值