LeetCode 837 概率dp

昨天pdd的笔试题 最后不想做了想清楚了自己的代码只满足了只走一步的情况就没做了 今天补一下

题意:输入m a r 该开始在0 每次随机走1~r步 如果当前小于a就继续走 求最后位置小于等于m的概率

/**
    昨天的代码1 没有考虑到到了a之后就不能再往后走了
*/
#include <bits/stdc++.h>

using namespace std;
const int N=1000;
double dp[N];//不超过i的概率
int main()
{
    int m,a,r;
    double ans;
    while(cin>>m>>a>>r)
    {
        if(m>r+a)
            ans=1;
        else
        {
            memset(dp,0,sizeof(dp));
            for(int i=0;i<a;i++)
                dp[i]=0;
            for(int i=r+a;i<N;i++)
                dp[i]=1;
            for(int i=a;i<a+r;i++)
            {
                for(int j=i+1;j<=i+r;j++)//确实是从j跳到i的
                {
                    dp[i]+=dp[j]/r;
                }
            }
            ans=dp[m];
            for(int i=0;i<=m;i++)
                ans+=dp[i];
        }
        cout<<fixed<<setprecision(5)<<ans<<endl;
    }
    return 0;
}

 

/**
    考试的时候的代码2
    这里其实考虑到了代码1中结束了还往前走的问题 但是又在起点的问题上混了
*/
#include <bits/stdc++.h>

using namespace std;
const int N=1000;
double dp[N];//跳到i的概率
int main()
{
    int m,a,r;
    double ans;
    while(cin>>m>>a>>r)
    {
        if(m>=r+a)
            ans=1;
        else
        {
            memset(dp,0,sizeof(dp));
            for(int i=0;i<a;i++)
                dp[i]=1.0;
            for(int i=a;i<a+r;i++)
            {
                for(int j=i+1-a;j<=r&&i>=j;j++)//确实是从j跳到i的
                {
                    dp[i]+=dp[i-j]/r;
                }
            }
            ans=0;
            for(int i=a;i<=m;i++)
                ans+=dp[i];
        }
        cout<<fixed<<setprecision(5)<<ans<<endl;
    }
    return 0;
}

 

/**
    今天的代码 TLE 113/146 
*/
#include <bits/stdc++.h>

using namespace std;
const int N=1000;
double dp[N];//跳到i的概率
int main()
{
    int m,a,r;
    double ans;
    while(cin>>m>>a>>r)
    {
        if(m>=r+a)
            ans=1;
        else
        {
            memset(dp,0,sizeof(dp));
            dp[0]=1.0;
            for(int i=1;i<a+r;i++)
            {
                for(int j=1;j<=r&&i>=j;j++)//确实是从j跳到i的
                {
                    if(i-j<a)
                        dp[i]+=dp[i-j]/r;
                }
            }
            ans=0;
            for(int i=a;i<=m;i++)
                ans+=dp[i];
        }
        cout<<fixed<<setprecision(5)<<ans<<endl;
    }
    return 0;
}
/**
    AC代码 重点在于这三个if 教训就是要随时在具体的含义和抽象的数学表达式里切换
*/
    if(m>=r+a||a==0)
            ans=1;
        else
        {
            dp[0]=1.0;
            for(int i=1;i<=m;i++)
            {
                if(i>1)
                    dp[i]=dp[i-1];
                if(i<=a)
                    dp[i]+=dp[i-1]/r;
                if(i>r)
                    dp[i]-=dp[i-1-r]/r;
            }
            ans=0;
            for(int i=a;i<=m;i++)
                ans+=dp[i];
        }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值