poj1322 概率dp(蜜汁优化技巧)

题目:

https://vjudge.net/problem/POJ-1322

 

这题是一道很普通的概率dp题目,但是如果不进行剪枝就会超时,而这题用的剪枝恰恰非常巧妙。

 

首先是思路分析:

当i+j时奇数还是偶数这个分析确实很难想到。(当然,没有这个条件也可以AC的)

 

而关于处时输入数据是否满足题目条件的判断就比较套路。

这个条件其实是对时间和空间同时进行优化,时间是for循环的次数,空间是dp数组的大小。

因为这题的M<=C是肯定的,所以只要开到110,但是如果没有这个剪枝,那么M>100时会越界。

 

关于dp的初始化是非常重要的,否则会得到所有数组的值都是0。而这里的初始化是dp[0][0]=1。(按照逻辑,dp[1][1]也是=1,但是i是从1开始的,而且j是从0开始的,而且开始的时候就要用到上一层的数组值,所以必须从(0,0)开始初始化)。

 

关于dp数组的定义:

double dp[2][MAXN];//dp[i][j]表示在操作了i次(取了i颗糖)后,桌面上剩余的巧克力的数量为j
这里用了滚动数组,数组第一维只有2个空间,而没有直接将他压缩成为1维数组,是因为:

dp[i][j]会同时用到dp[i-1][j-1]和dp[i-1][j+1],而dp[i][j+1]会用到dp[i-1][j]和dp[i-1][j+2],两个压缩一下就变成:

dp[j]=dp[j-1]*...+dp[j+1]*...和dp[j+1]=dp[j]*...+dp[j+2]*....,这时无论怎么调整for循环中的i和j的顺序都不能保证不覆盖,所以必须用二维数组。

 

最后是关于这一步:

因为最后输出结果时决定是奇数还是偶数,所以N=1000还是1001要判断。

因为只要三位小数,精度很低,所以1000次运算足矣(证明不清楚)

 

还有另一种方法:

方法来自:https://blog.youkuaiyun.com/non_cease/article/details/6895083

 

我的代码:
 

//poj1322
#include<stdio.h>
#include<string.h>
#define MAXN 110

double dp[2][MAXN];//dp[i][j]表示在操作了i次(取了i颗糖)后,桌面上剩余的巧克力的数量为j

int main()
{
    int i,j;
    int C,N,M;
    int temp;

    while(scanf("%d",&C)&&C)
    {
        scanf("%d%d",&N,&M);
        memset(dp,0,sizeof(dp));
        dp[0][0]=1.0;
        if(M>100||M>C||M>N)
        {
            printf("%.3f\n",0.0);
            continue;
        }
        temp=N;
        if(N>1000)
            N=1000+(N%2);
        for(i=1;i<=N;i++)
        {
            for(j=0;j<=i&&j<=C;j++)
            {
                /*if((i+j)%2!=0)
                    dp[i%2][j]=0;
                else*/
                    dp[i%2][j]=dp[(i-1+2)%2][j-1]*((C-j+1)*1.0/C)+dp[(i-1+2)%2][j+1]*((j+1)*1.0/C);
                if(i==N&&j==M)
                    break;
            }
            if(i==N)
                break;
        }
        printf("%.3f\n",dp[temp%2][M]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值