ZOJ3822 ACM-ICPC 2014 亚洲区域赛牡丹江赛区现场赛D题Domination 概率DP(两种解法)

题目地址:点击打开链接

这道题有两种做法,第一种是直接求期望,类似于poj 2096 区别在于这个步数有限。所以要迭代步数。

#include <cstdio>
#include <cstring>
#include <iostream>
#define maxn 55//这里刚开始写成了50+10 那么maxn*maxn就会小很多wa了一次
using namespace std;
double dp[maxn][maxn][maxn*maxn];
int N,M,T;
int main()
{
    while(~scanf("%d", &T))while(T--)
    {
        scanf("%d%d",&N,&M);
        memset(dp,0,sizeof(dp));
        for(int i=N;i>=0;i--)
            for(int j=M;j>=0;j--)
            {
                if(i==N && j==M) continue;//状态定义:dp[i][j][k] 走了k步覆盖了i行j列,此情况下能完全覆盖的期望
                for(int k=i*j;k>=max(i,j);k--)//步数不可能比i*j更多也要大于i,j中最大值因为已经覆盖了这么些
                {
                    double p0=1.0*(i*j-k)/(N*M-k);
                    double p1=1.0*(M-j)*i/(N*M-k);
                    double p2=1.0*(N-i)*j/(N*M-k);
                    double p3=1.0*(N-i)*(M-j)/(N*M-k);
                    dp[i][j][k]=dp[i][j][k+1]*p0+dp[i][j+1][k+1]*p1+dp[i+1][j][k+1]*p2+dp[i+1][j+1][k+1]*p3+1;
                }
            }
        printf("%.12lf\n",dp[0][0][0]);
    }
    return 0;
}


第二种是求概率,完事以后再算期望。(若是对于不限步数的题目来说这个方法是不能用的)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;
double dp[55][55][55*55];
const double eps=1e-8;

int main()
{
  //  freopen("in.txt","r",stdin);
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        memset(dp,0,sizeof(dp));
        memset(a,0,sizeof(a));
        dp[1][1][1]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(i==n && j==m) break;
                for(int k=max(i,j);k<=i*j;k++)
                {
                    dp[i][j][k+1]+=dp[i][j][k]*(i*j-k)/(n*m-k);
                    dp[i+1][j][k+1]+=dp[i][j][k]*(n-i)*j/(n*m-k);
                    dp[i][j+1][k+1]+=dp[i][j][k]*(m-j)*i/(n*m-k);
                    dp[i+1][j+1][k+1]+=dp[i][j][k]*(n-i)*(m-j)/(n*m-k);
                }
            }
        }
        double sum=0;
        for(int i=max(n,m);i<=n*m;i++)
            sum+=dp[n][m][i]*i;
        printf("%.12f\n",sum);
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值