昨天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];
}