码迷,mamicode.com
首页 > 其他好文 > 详细

[概率dp] ZOJ 3822 Domination

时间:2014-10-14 16:20:08      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:blog   io   os   for   sp   2014   on   log   代码   

题意:

给N×M的棋盘,每天随机找一个没放过棋子的格子放一个棋子

问使得每个每列都有棋子的天数期望

思路:

dp[i][j][k] 代表放了i个棋子占了j行k列 到达目标状态的期望

然后从 dp[n*m][n][m] 往后递推就好了。

因为知道了有i个棋子 例如一个状态dp[6][3][3]

x x x o o o

x o o o o o

x o x o o o

o o o o o o

对于 dp[i+1][3][3] 其实就是3*3剩下的空再放一个,概率就是(j*k-i) / (n*m-i)

对于 dp[i+1][4][3] 就是剩下的行乘上现有的列找一个放,概率就是  ((n-j)*k)/(n*m-i)

对于 dp[i+1][3][4]就是剩下的列乘上现有的行找一个放 ,概率就是 ((m-k)*j)/(n*m-i)

最后 dp[i+1][4][4] 就是剩下的行乘上剩下的列找一个放 ,概率就是(n-j)*(m-k))/(n*m-i)

然后期望是一天加上就好了。

注意一下几个非法的情况就好了

然后可以用滚动数组优化空间!

代码:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
#include"map"
#include"string"
using namespace std;
double dp[2][55][55];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        int i,j,k;
        memset(dp,0,sizeof(dp));
        for(i=n*m;i>=0;i--)
        {
            for(j=n;j>=0;j--)
            {
                for(k=m;k>=0;k--)
                {
                    if(j==n&&k==m) continue; //最终状态  期望是0
                    if(i>j*k) continue;  //棋子多了 非法
                    double tep=0;  //下面的注意不能等于0
                    if(j>0&&k>0) tep+=(dp[1-(i+1)%2][j][k]+1)*((j*k-i)/(n*m-i*1.0));
                    if(k>0) tep+=(dp[1-(i+1)%2][j+1][k]+1)*(((n-j)*k)/(n*m-i*1.0));
                    if(j>0) tep+=(dp[1-(i+1)%2][j][k+1]+1)*(((m-k)*j)/(n*m-i*1.0));
                    tep+=(dp[1-(i+1)%2][j+1][k+1]+1)*((n-j)*(m-k))/(n*m-i*1.0);
                    dp[1-(i)%2][j][k]=tep;
                }
            }
        }
        printf("%.12f\n",dp[1-(0)%2][0][0]);
    }
    return 0;
}


[概率dp] ZOJ 3822 Domination

标签:blog   io   os   for   sp   2014   on   log   代码   

原文地址:http://blog.csdn.net/wdcjdtc/article/details/40075371

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!