P1409题解
P1409 题解
博客里食用更佳。
题意
题目的意思浅显易懂:
n 个人站成一排,小明(临时演员)是第 m 个人,每轮上帝会投一次筛子,分为以下情况:
- 若掷到 1,则队首的人获胜;
- 若掷到 2,4,6,则队首的人出队;
- 若掷到 3,5,则队首的人排到队尾。
问:小明有多少的胜率?(注意:输出保留九位小数)
思路
这不就是一道 dp 和数学结合起来的题吗???
分析
我们就设二维数组 f[1005][1005],f[i][j] 表示有 i 个人,小明在第 j 个位置,小明的胜率。
易知,f[1][1]=1,因为只有一个人的时候小明直接胜利!且由题意得 j⩽i。
接下来,我们需要把题目带进来,求出状态转移方程式(动态规划的递推式)。
- 掷到 1,则队首的人获胜,这时候,小明有 16 的概率会输掉(对手的人胜利了,小明就输了)。
- 掷到 2,4,6,则队首的人出队,此时,队首的人有 12 的概率会转回队尾,(那又是一个天道好轮回了……)也就是相当于小明又往前走了一步(j−1),而总人数(i)不变,表示为 f[i][j−1]。
- 掷到 3,5,则队首的人排到队尾,此时,队首的人有 13 的概率出队,也就是相当于小明又往前走了一步(j−1),而总人数却又少了一个人(i−1),表示为 f[i−1][j−1]。
列出了上表,dp递推式也就很简单了,由于小明为主角,绝不能输,所以就不讨论第一种情况,所以,对于 x,y(x⩽y,x,y 为正整数),都有 f[x][y],此时有 12 的概率跳到 f[x][y−1];有 13 的概率跳到 f[x−1][y−1] 所以推出动态规划递推式:
f[x][y]=12f[x][y−1]+13f[x−1][y−1]。
最后小明就会跳到 f[u][1](u 为正整数且 u⩽n)(这里 u 是代表当小明为第一个人时,总共还剩几人),小明就到了第一个,上帝要为他摇骰子了!而当小明为第一个时,j=1,所以没有 f[u][0] 或 f[u−1][0],所以我们要单独推当 j=1 时的情况:他有 16 的概率会胜利,而又会有 13 的概率出局(要求小明的胜率,这种情况不讨论),也有 12 跳到队尾,也就是跳到 f[u][u](又是一个天道好轮回),所以 f[u][1]=16+12f[u][u]。
这就可以推广到所有 j=1 时的情况,因此我们就会建立这么多个循环往复的等式,这是一个连续的多元一次方程组,是容易解决的,观察一下系数,然后就可以用代入消元法解决了。(谢谢 Aw顿顿 )
观察系数的代码如下:
for(int j=2; j<=i; j++){//观察系数
sum=sum/2;
num=num/2+f[i-1][j-1]/3;
}
总结:
- 坑点(也不算吧):输出保留九位小数。
- 需要的基础:dp+数学(数论)。
- dp 比较别致一点,因为 dp 数列可能会构成一个环,所以须要观察系数,然后就可以用代入消元法解决了。
- 当小明第一个人时,若遇到第二种情况,还需要重新排到队尾,千万不可结束,不然听取 WA 声一片。
废话不多说了,上总代码!
注释在代码里了
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
double f[1005][1005];
int main(){
cin>>n>>m;
f[1][1]=1;//初始化!只有一个人的时候你直接胜利!别忘了写这一行
for(int i=2; i<=n; i++){
double sum=0.5,num=1.0/6.0;
//1.0/6.0和1/6可有大区别了!
//1/6=0.166666667……,取整一下为0
//1.0/6.0则是相当于(double)1/6
for(int j=2; j<=i; j++){//观察系数
sum=sum/2;
num=num/2+f[i-1][j-1]/3;
}
//不断将f[i][j-1]带入f[i][j],最终就可以求出下面二式
f[i][i]=num/(1-sum);//解出了f[i][i]
f[i][1]=f[i][i]/2+1.0/6.0;//解出了f[i][1]
for(int j=2; j<i; j++) f[i][j]=f[i][j-1]/2+f[i-1][j-1]/3;//前面推出的解析式(递推式?到底说算是什么啊……)
}
printf("%.9lf",f[n][m]);//保留九位输出
return 0;
}
//P上水印
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现