原文来自:http://blog.csdn.net/wdcjdtc/article/details/38424029

首先,概率dp主要解决的是关于概率问题和期望问题的求解。

难点和普通dp一样在于dp[i][j][k]的维数控制和含义,其实就是转移方程的构建。

然后一般地,求概率是正推、求期望是逆推。(开始的很多状态不可能发生概率为0,最后的状态出口期望为0)

对于求概率当前点的概率是由前面能到达当前点的点乘上到达当前点的概率得到的。

也就是dp[i]=Σ(dp[j]*p[j][i])  i是当前点、j是前面的点。

对于求期望当前点的期望是由当前点所能到达的点得到的。(注意下,对应的概率是当前点到达之后点的概率,因为你要到达后面的点后面的点才能传递给你期望!)

也就是E[i]=Σ((E[j]+k)*p[i][j])  i是当前点、j是当前点所能到达的点,k是所需的期望值。

然后就是对于期望的话,如果成环的话数据范围小的话可以用高斯消元解决(之前的博文提到),如果范围大就要推导公式了(后面的题目有提到)。

poj  2096 Collecint Bugs

dp求期望入门题。

题意,思路,公式引用别人的:http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710606.html

dp求期望
逆着递推求解
题意:(题意看题目确实比较难道,n和s都要找半天才能找到)一个软件有s个子系统,会产生n种bug某人一天发现一个bug,这个bug属于一个子系统,属于一个分类每个bug属于某个子系统的概率是1/s,属于某种分类的概率是1/n问发现n种bug,每个子系统都发现bug的天数的期望。求解:dp[i][j]表示已经找到i种bug,j个系统的bug,达到目标状态的天数的期望dp[n][s]=0;要求的答案是dp[0][0];dp[i][j]可以转化成以下四种状态:dp[i][j],发现一个bug属于已经有的i个分类和j个系统。概率为(i/n)*(j/s);dp[i][j+1],发现一个bug属于已有的分类,不属于已有的系统.概率为 (i/n)*(1-j/s);dp[i+1][j],发现一个bug属于已有的系统,不属于已有的分类,概率为 (1-i/n)*(j/s);dp[i+1][j+1],发现一个bug不属于已有的系统,不属于已有的分类,概率为 (1-i/n)*(1-j/s);整理便得到转移方程

代码:

[cpp] view plain copy
  1. #include"cstdlib"
  2. #include"cstdio"
  3. #include"cstring"
  4. #include"cmath"
  5. #include"queue"
  6. #include"algorithm"
  7. #include"iostream"
  8. #define eps 1e-5
  9. using namespace std;
  10. double dp[1020][1020];
  11. int main()
  12. {
  13. int n,s;
  14. while(cin>>n>>s)
  15. {
  16. memset(dp,0,sizeof(dp));
  17. for(int i=n; i>=0; i--)
  18. {
  19. for(int j=s; j>=0; j--)
  20. {
  21. if(i==n&&j==s) continue;
  22. double tep=1.0;
  23. if(i<n) tep+=(n*1.0-i)*j/(n*s)*dp[i+1][j];
  24. if(j<s) tep+=(s*1.0-j)*i/(n*s)*dp[i][j+1];
  25. if(i<n&&j<s) tep+=(n*1.0-i)*(s*1.0-j)/(n*s)*dp[i+1][j+1];
  26. dp[i][j]=tep/(1-(i*j*1.0)/(s*n));
  27. }
  28. }
  29. printf("%.4f\n",dp[0][0]);
  30. }
  31. return 0;
  32. }

类似的简单题:

hdu 3853     注意停留原地的情况,应该跳过不处理。还有一点走一步的期望是2。
hdu 4405     处理一下连续移动的情况
SGU 495      用概率求期望
CF 148D   考虑下边界就OK了,方程很好推

zoj 3640 Help Me Escape

题意:

一只吸血鬼,有n条路给他走,每次他随机走一条路,

每条路有个限制,如果当时这个吸血鬼的攻击力大于等于某个值,那么就会花费t天逃出去。

否则,花费1天的时间,并且攻击力增加,问他逃出去的期望天数。

思路:

方程很好像  dp[i] 有i点战斗力逃出去的期望

那么如果  x>c[i]时 dp[i]=(1.0/n)*Σt[i]

否则   dp[i]=(1.0/n)*Σ(dp[i+c[i]]+1)

因为很多点会被重复用,所以写成记忆化搜索。

还有一个要注意的,t[i]是向下取整的。

代码:

[cpp] view plain copy
  1. #include"cstdlib"
  2. #include"cstdio"
  3. #include"cstring"
  4. #include"cmath"
  5. #include"queue"
  6. #include"algorithm"
  7. #include"iostream"
  8. #define eps 1e-12
  9. using namespace std;
  10. #define N 10020
  11. double dp[N];
  12. int c[123];
  13. int t[123];
  14. int MAX;
  15. int n,f;
  16. double dfs(int x)
  17. {
  18. if(x>MAX) x=MAX;  //小优化  超过最大值 就为最大值
  19. if(fabs(dp[x]+1)>eps) return dp[x];
  20. double tep=0.0;
  21. for(int i=1;i<=n;i++)
  22. {
  23. if(x>c[i]) tep+=1.0/n*t[i];
  24. else tep+=1.0/n*(dfs(x+c[i])+1);
  25. }
  26. return dp[x]=tep;
  27. }
  28. int main()
  29. {
  30. while(cin>>n>>f)
  31. {
  32. int i;
  33. MAX=-1;
  34. memset(dp,-1,sizeof(dp));
  35. for(i=1;i<=n;i++)
  36. {
  37. scanf("%d",&c[i]);
  38. MAX=max(MAX,c[i]+1);
  39. t[i]=(int)((1+sqrt(5.0))/2*c[i]*c[i]);  //这里要注意了  t[i]是一个向下取整的!
  40. }
  41. dp[f]=dfs(f);
  42. printf("%.3f\n",dp[f]);
  43. }
  44. return 0;
  45. }

poj 3744 Scout YYF I

其实概率方程很简单,就是有地雷的时候那个点是不能得到其他点的概率要是0.

然后就是分段的思想了,按区间分步求,起点是1,终点MAX+1。

然后需要注意的是:

1、有可能1是雷,你直接爆炸~ bomb :) ~

2、范围很大,需要用矩阵快速幂优化

3、雷不是有序的,要记得排序

代码:

[cpp] view plain copy
  1. #include"cstdlib"
  2. #include"cstdio"
  3. #include"cstring"
  4. #include"cmath"
  5. #include"queue"
  6. #include"algorithm"
  7. #include"iostream"
  8. #define eps 1e-12
  9. using namespace std;
  10. #define N 10020
  11. struct matrix
  12. {
  13. double mat[3][3];
  14. };
  15. matrix matmul(matrix a,matrix b,int n)
  16. {
  17. int i,j,k;
  18. matrix c;
  19. memset(c.mat,0,sizeof(c.mat));
  20. for(i=0; i<n; i++) for(j=0; j<n; j++) for(k=0; k<n; k++) c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
  21. return c;
  22. }
  23. matrix matpow(matrix a,int k,int n)
  24. {
  25. matrix b;
  26. int i;
  27. memset(b.mat,0,sizeof(b.mat));
  28. for(i=0; i<n; i++) b.mat[i][i]=1;
  29. while(k)
  30. {
  31. if(k&1) b=matmul(a,b,n);
  32. a=matmul(a,a,n);
  33. k>>=1;
  34. }
  35. return b;
  36. }
  37. int main()
  38. {
  39. int n;
  40. double p;
  41. while(scanf("%d%lf",&n,&p)!=-1)
  42. {
  43. double q=1-p;
  44. int i;
  45. int mine[23];
  46. for(i=0; i<n; i++)  scanf("%d",&mine[i]);
  47. sort(mine,mine+n);
  48. int k=0;
  49. matrix ans,a,b,c;
  50. memset(a.mat,0,sizeof(a.mat));
  51. memset(b.mat,0,sizeof(b.mat));
  52. memset(c.mat,0,sizeof(c.mat));
  53. if(mine[k]==1)
  54. {
  55. puts("0.0000000");
  56. continue;
  57. }
  58. else if(mine[k]==2)
  59. {
  60. a.mat[0][0]=0;
  61. a.mat[0][1]=1;
  62. k++;
  63. }
  64. else
  65. {
  66. a.mat[0][0]=p;
  67. a.mat[0][1]=1;
  68. }
  69. int yuan=2;
  70. b.mat[0][0]=p;
  71. b.mat[1][0]=q;
  72. b.mat[0][1]=1;
  73. c=b;
  74. for(i=k;i<n;i++)
  75. {
  76. c=b;
  77. ans=matmul(a,matpow(c,mine[i]-yuan-1,2),2);
  78. a.mat[0][0]=0;
  79. a.mat[0][1]=ans.mat[0][0];
  80. yuan=mine[i];
  81. }
  82. ans=matmul(a,matpow(c,mine[n-1]+1-yuan,2),2);
  83. printf("%.7f\n",ans.mat[0][0]);
  84. }
  85. return 0;
  86. }

还有几道中等的题目:

poj 2151  dp[i][j][k]第i个人在前j题中做出了k题的概率  最后所有人至少作出一道题的概率减去所有人都做1~N-1题的概率 即为所求
poj 3071  全概率公式  巧妙确定范围的方法

[cpp] view plain copy
  1. for(i=0; i<(1<<n); i++) dp[0][i]=1;
  2. for(i=1; i<=n; i++)
  3. {
  4. for(j=0; j<(1<<n); j++)
  5. {
  6. int tep=j/(1<<(i-1));
  7. tep^=1;
  8. int s=tep*(1<<(i-1));
  9. int e=tep*(1<<(i-1))+(1<<(i-1));
  10. for(k=s; k<e; k++)
  11. dp[i][j]+=dp[i-1][j]*dp[i-1][k]*p[j][k];
  12. }
  13. }

以下几题都比较难了:

hdu 4089 Activation

题意:有n个人排队等着在官网上激活游戏。Tomato排在第m个。
对于队列中的第一个人。有一下情况:
1、激活失败,留在队列中等待下一次激活(概率为p1)
2、失去连接,出队列,然后排在队列的最后(概率为p2)
3、激活成功,离开队列(概率为p3)
4、服务器瘫痪,服务器停止激活,所有人都无法激活了。
求服务器瘫痪时Tomato在队列中的位置<=k的概率解析:
概率DP;
设dp[i][j]表示i个人排队,Tomato排在第j个位置,达到目标状态的概率(j<=i)
dp[n][m]就是所求
j==1:    dp[i][1]=p1*dp[i][1]+p2*dp[i][i]+p4;
2<=j<=k: dp[i][j]=p1*dp[i][j]+p2*dp[i][j-1]+p3*dp[i-1][j-1]+p4;
k<j<=i:  dp[i][j]=p1*dp[i][j]+p2*dp[i][j-1]+p3*dp[i-1][j-1];
化简:
j==1:    dp[i][1]=p*dp[i][i]+p41;
2<=j<=k: dp[i][j]=p*dp[i][j-1]+p31*dp[i-1][j-1]+p41;
k<j<=i:  dp[i][j]=p*dp[i][j-1]+p31*dp[i-1][j-1];其中:
p=p2/(1-p1);
p31=p3/(1-p1)
p41=p4/(1-p1)可以循环i=1->n 递推求解dp[i].在求解dp[i]的时候dp[i-1]就相当于常数了。
在求解dp[i][1~i]时等到下列i个方程
j==1:   dp[i][1]=p*dp[i][i]+c[1];
2<=j<=k:dp[i][j]=p*dp[i][j-1]+c[j];
k<j=i:  dp[i][j]=p*dp[i][j]+c[j];
其中c[j]都是常数了。上述方程可以解出dp[i]了。
首先是迭代得到 dp[i][i].然后再代入就可以得到所有的dp[i]了。注意特判一种情况。就是p4<eps时候,就不会崩溃了,应该直接输出0

代码:

[cpp] view plain copy
  1. #include"cstdlib"
  2. #include"cstdio"
  3. #include"cstring"
  4. #include"cmath"
  5. #include"queue"
  6. #include"algorithm"
  7. #include"iostream"
  8. #define eps 1e-12
  9. using namespace std;
  10. double dp[2022][2022];
  11. int main()
  12. {
  13. int n,m,k;
  14. double p1,p2,p3,p4;
  15. while(cin>>n>>m>>k>>p1>>p2>>p3>>p4)
  16. {
  17. memset(dp,0,sizeof(dp));
  18. int i,j;
  19. double p22,p33,p44;
  20. p22=p2/(1-p1);
  21. p33=p3/(1-p1);
  22. p44=p4/(1-p1);
  23. if(fabs(p4)<=eps)
  24. {
  25. puts("0.00000");
  26. continue;
  27. }
  28. dp[1][1]=p44/(1-p22);
  29. for(i=2;i<=n;i++)
  30. {
  31. double p=1.0,tep=0.0;
  32. for(j=i;j>=1;j--,p*=p22)       //中间就是迭代求出其中一个,因为五个方程五个未知数,形式相等。
  33. {
  34. if(j==1) tep+=p*p44;
  35. else if(j>=2&&j<=k) tep+=p*(p33*dp[i-1][j-1]+p44);
  36. else tep+=p*p33*dp[i-1][j-1];
  37. }
  38. dp[i][i]=tep/(1-p);
  39. for(j=1;j<i;j++)
  40. {
  41. if(j==1) dp[i][j]=p22*dp[i][i]+p44;
  42. else if(j>=2&&j<=k) dp[i][j]=p22*dp[i][j-1]+p33*dp[i-1][j-1]+p44;
  43. else dp[i][j]=p22*dp[i][j-1]+p33*dp[i-1][j-1];
  44. }
  45. }
  46. printf("%.5f\n",dp[n][m]);
  47. }
  48. return 0;
  49. }

zoj 3329 One Person Game

题意:有三个骰子,分别有k1,k2,k3个面,人物开始分数为零。

每次掷骰子,如果三个面分别是a,b,c的话分数归零,否则分数加上三个骰子的点数和。

分数超过n则游戏结束。求游戏结束的期望掷骰子次数。

思路: 设投出a,b,c 的概率为p0,投出k分的概率为p[k]

则对于每个分数 dp[i]=p0*dp[0]+Σ(dp[i+k]*p[k])+1    ①

又设 dp[i]=A[i]dp[0]+B[i]     ②,则dp[i+k]=A[i+k]dp[0]+B[i+k]

代入① 得:  dp[i]=p0*dp[0]+Σ((A[i+k]dp[0]+B[i+k])*p[k])+1

化简得: dp[i]=(p0+Σ(A[i+k]*p[k]))*dp[0] + Σ(B[i+k]*p[k]) +1

对比②得: A[i]=Σ(A[i+k]*p[k])+p0

B[i]=Σ(B[i+k]*p[k]) +1

当i+k>n时A[i+k]=B[i+k]=0
所以dp[0]=B[0] / (1-A[0])可求出

代码:

[cpp] view plain copy
  1. #include"cstdlib"
  2. #include"cstdio"
  3. #include"cstring"
  4. #include"cmath"
  5. #include"queue"
  6. #include"algorithm"
  7. #include"iostream"
  8. #define eps 1e-12
  9. using namespace std;
  10. int main()
  11. {
  12. int t;
  13. cin>>t;
  14. while(t--)
  15. {
  16. int n,k[4],a,b,c;
  17. int i,j,l;
  18. scanf("%d%d%d%d%d%d%d",&n,&k[1],&k[2],&k[3],&a,&b,&c);
  19. double p[22];
  20. memset(p,0,sizeof(p));
  21. for(i=1;i<=k[1];i++) for(j=1;j<=k[2];j++) for(l=1;l<=k[3];l++) p[i+j+l]+=1.0/(k[1]*k[2]*k[3]);  //求出掷出k点的概率
  22. p[a+b+c]-=1.0/(k[1]*k[2]*k[3]);  //单独考虑下分别a,b,c点的情况
  23. p[0]=1.0/(k[1]*k[2]*k[3]);
  24. double A[600],B[600];
  25. memset(A,0,sizeof(A));
  26. memset(B,0,sizeof(B));
  27. for(i=n;i>=0;i--)           //递推求解
  28. {
  29. A[i]=p[0];
  30. B[i]=1;
  31. if(i==n) continue;
  32. for(j=1;j<=k[1]+k[2]+k[3];j++)
  33. {
  34. A[i]+=p[j]*A[i+j];
  35. B[i]+=p[j]*B[i+j];
  36. }
  37. }
  38. printf("%.15f\n",B[0]/(1-A[0]));
  39. }
  40. return 0;
  41. }

总结下这类概率DP:
既DP[i]可能由DP[i+k]和DP[i+j]需要求的比如DP[0]决定
相当于概率一直递推下去会回到原点 
比如
(1):DP[i]=a*DP[i+k]+b*DP[0]+d*DP[i+j]+c;
但是DP[i+k]和DP[0]都是未知
这时候根据DP[i]的方程式假设一个方程式:
比如:
(2):DP[i]=A[i]*DP[i+k]+B[i]*DP[0]+C[i];
因为要求DP[0],所以当i=0的时候但是A[0],B[0],C[0]未知
对比(1)和(2)的差别 
这时候对比(1)和(2)发现两者之间的差别在于DP[i+j]
所以根据(2)求DP[i+j]然后代入(1)消除然后对比(2)就可以得到A[i],B[i],C[i]
然后视具体情况根据A[i],B[i],C[i]求得A[0],B[0],C[0]继而求DP[0]

然后下面那题可以好好感受一下这个!

hdu 4035 Maze

经典的概率dp,关于成环的概率dp的求解,公式的推导。

题意,思路,公式引用别人的:http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710606.html

dp求期望的题。题意:有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树,从结点1出发,开始走,在每个结点i都有3种可能:1.被杀死,回到结点1处(概率为ki)2.找到出口,走出迷宫 (概率为ei)3.和该点相连有m条边,随机走一条
求:走出迷宫所要走的边数的期望值。设 E[i]表示在结点i处,要走出迷宫所要走的边数的期望。E[1]即为所求。叶子结点:E[i] = ki*E[1] + ei*0 + (1-ki-ei)*(E[father[i]] + 1);= ki*E[1] + (1-ki-ei)*E[father[i]] + (1-ki-ei);非叶子结点:(m为与结点相连的边数)E[i] = ki*E[1] + ei*0 + (1-ki-ei)/m*( E[father[i]]+1 + ∑( E[child[i]]+1 ) );= ki*E[1] + (1-ki-ei)/m*E[father[i]] + (1-ki-ei)/m*∑(E[child[i]]) + (1-ki-ei);设对每个结点:E[i] = Ai*E[1] + Bi*E[father[i]] + Ci;对于非叶子结点i,设j为i的孩子结点,则∑(E[child[i]]) = ∑E[j]= ∑(Aj*E[1] + Bj*E[father[j]] + Cj)= ∑(Aj*E[1] + Bj*E[i] + Cj)带入上面的式子得(1 - (1-ki-ei)/m*∑Bj)*E[i] = (ki+(1-ki-ei)/m*∑Aj)*E[1] + (1-ki-ei)/m*E[father[i]] + (1-ki-ei) + (1-ki-ei)/m*∑Cj;由此可得Ai =        (ki+(1-ki-ei)/m*∑Aj)   / (1 - (1-ki-ei)/m*∑Bj);Bi =        (1-ki-ei)/m            / (1 - (1-ki-ei)/m*∑Bj);Ci = ( (1-ki-ei)+(1-ki-ei)/m*∑Cj ) / (1 - (1-ki-ei)/m*∑Bj);对于叶子结点Ai = ki;Bi = 1 - ki - ei;Ci = 1 - ki - ei;从叶子结点开始,直到算出 A1,B1,C1;E[1] = A1*E[1] + B1*0 + C1;所以E[1] = C1 / (1 - A1);若 A1趋近于1则无解...

代码:

[cpp] view plain copy
  1. #include"cstdlib"
  2. #include"cstdio"
  3. #include"cstring"
  4. #include"cmath"
  5. #include"queue"
  6. #include"algorithm"
  7. #include"iostream"
  8. #define eps 1e-12        //注意开1e-8会WA
  9. #include"vector"
  10. #define N 10010
  11. using namespace std;
  12. struct node
  13. {
  14. int v,w;
  15. node(int vv)
  16. {
  17. v=vv;
  18. }
  19. };
  20. vector<node>edge[N];
  21. double A[N],B[N],C[N],Asum[N],Bsum[N],Csum[N];
  22. double p[N],e[N];
  23. void dfs(int u,int f)    //最简单的对树的搜索
  24. {
  25. int n=edge[u].size();
  26. if(n==1&&u!=1)          //如果是叶子节点
  27. {
  28. A[u]=Asum[u]=p[u];
  29. B[u]=Bsum[u]=1-p[u]-e[u];
  30. C[u]=Csum[u]=1-p[u]-e[u];
  31. return ;
  32. }
  33. Asum[u]=Bsum[u]=Csum[u]=0;
  34. for(int i=0;i<n;i++)  //不是叶子节点的 按公式求值
  35. {
  36. if(edge[u][i].v==f) continue;
  37. dfs(edge[u][i].v,u);
  38. Asum[u]+=A[edge[u][i].v];
  39. Bsum[u]+=B[edge[u][i].v];
  40. Csum[u]+=C[edge[u][i].v];
  41. A[u]=(p[u]+(1-p[u]-e[u])/n*Asum[u])          /(1-(1-p[u]-e[u])/n*Bsum[u]);
  42. B[u]=((1-p[u]-e[u])/n)                       /(1-(1-p[u]-e[u])/n*Bsum[u]);
  43. C[u]=((1-p[u]-e[u])+(1-p[u]-e[u])/n*Csum[u]) /(1-(1-p[u]-e[u])/n*Bsum[u]);
  44. }
  45. return ;
  46. }
  47. int main()
  48. {
  49. int t,cas=1;
  50. cin>>t;
  51. while(t--)
  52. {
  53. int n,i;
  54. cin>>n;
  55. for(i=0;i<=n;i++)
  56. edge[i].clear();
  57. for(i=1;i<=n-1;i++)
  58. {
  59. int a,b;
  60. scanf("%d%d",&a,&b);
  61. edge[a].push_back(node(b));
  62. edge[b].push_back(node(a));
  63. }
  64. for(i=1;i<=n;i++)     //注意读进来的数是百分比
  65. {
  66. scanf("%lf%lf",&p[i],&e[i]);
  67. p[i]*=0.01;
  68. e[i]*=0.01;
  69. }
  70. dfs(1,1);
  71. printf("Case %d: ",cas++);
  72. if(fabs(1-A[1])<=eps)       //不断被杀死 逃不出去 T_T
  73. {
  74. puts("impossible");
  75. continue;
  76. }
  77. printf("%.6f\n",C[1]/(1-A[1]));
  78. }
  79. return 0;
  80. }

关于概率dp的个人理解与总结相关推荐

  1. 【原创】概率DP总结 by kuangbin

    概率DP主要用于求解期望.概率等题目. 转移方程有时候比较灵活. 一般求概率是正推,求期望是逆推.通过题目可以体会到这点. 首先先推荐几篇参考的论文: <信息学竞赛中概率问题求解初探> & ...

  2. 【CodeForces - 518D】Ilya and Escalator(概率dp,数学期望)

    题干: Ilya got tired of sports programming, left university and got a job in the subway. He was given ...

  3. Codeforces 678E. Another Sith Tournament(概率DP,状压)

    Codeforces 678E. Another Sith Tournament 题意: n(n<=18)个人打擂台赛,给定任意两人对决的胜负概率,比赛规则:可指定一人作为最开始的擂主,每次可指 ...

  4. 插头DP 概率DP / 期望DP

    插头DP && 概率DP / 期望DP 写在前面: 插头DP P5056 [模板]插头dp 手写哈希表的方法: 拉链法的代码如下: 开放寻址法的代码如下: 接下来是这道题的代码实现: ...

  5. GalaxyOJ-636 (概率DP)

    题目 Problem Description LLY作为信奥班唯一的妹子,始终保持着那份纯真,看她正在为箱子涂色.LLY现在有c种颜色,编号为0~c-1:还有n个箱子,编号为1~n,最开始每个箱子的颜 ...

  6. 【CCPC-Wannafly Winter Camp Day4 (Div1) H】命命命运(概率DP)

    点此看题面 大致题意: 有\(6\)个人玩大富翁,共有\(n\)块地,进行\(500\)轮,已知每个人掷骰子掷出\(1\sim6\)的概率.当某人到达一块未被占领的地时,他可以占领它.求最后每个人占有 ...

  7. [BZOJ4899]:记忆的轮廓(概率DP)

    题目传送门 题目描述: 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...

  8. 动态规划报告(树形DP+概率DP

    动态规划报告 树形dp 树形 DP,即在树上进行的 DP.由于树固有的递归性质,树形 DP 一般都是递归进行的.一般需要在遍历树的同时维护所需的信息 以一道题目为例 2022CCPC桂林站G Grou ...

  9. 运动会(第一次接触概率DP的我黯然神伤)

    运动会 题目描述:有n个项目,m个人,lzj每个项目的排名分别是a[1]-a[i],假设其他m-1 个人在每个子项目的比赛中获得各名次的概率相同,求他自己最后排名的期望值 样例 input 4 10 ...

最新文章

  1. HttpClient(4.5.x)正确的使用姿势
  2. mysql unescape解码_PHP解密Unicode及Escape加密字符串
  3. 【Get 以太坊技能】CentOS 7 Geth安装
  4. python 残差图_python 残差图
  5. 05.序列模型 W2.自然语言处理与词嵌入
  6. Oracle Groundbreakers 亚太巡演 2021中国区精彩抢先看
  7. XP计算机调整对比度,Win7系统调节显示器屏幕对比度的两种方法【图文】
  8. 二维高斯曲面拟合法求取光斑中心及算法的C++实现
  9. Linux下服务器搭建(1)——Linux下搭建FTP服务器 vsftpd服务
  10. 深入Atlas系列:客户端网络访问基础结构(上) - WebRequest的工作流程与生命周期...
  11. vmware硬件兼容官方查询地址
  12. Jeesite框架IDEA导入,部署,启动,打包
  13. 2012 r2 万能网卡驱动_无线网卡怎么用,我来教您无线网卡怎么用的方法
  14. iphone 扩容测试软件,拯救iPhone 12 64G!闪迪打造的扩容神器上手:轻松省钱
  15. 未来教育计算机上机题库,未来教育版计算机二级C语言上机题库(含答案)
  16. 学生信息管理系统(头哥适用版)(c语言)
  17. set的用法及短语_set的用法总结大全
  18. android 键盘将底部视图顶起,android 弹出软键盘将底部视图顶起问题
  19. JS显示团购剩下时间的代码整理
  20. 博客园自定义(全部样式分享)

热门文章

  1. 产品经理如何做好需求调研
  2. Maven 参数详情
  3. halcon印章文字提取
  4. Blast中文手册(1)
  5. 三星970PRO用于高速采集存储系统
  6. 万维钢:发现效率的眼睛
  7. RGB颜色规律小研究
  8. 陪着时光,走过羊肠阡陌
  9. selenium2java 截图保存桌面(内含一坑)
  10. HNU暑假程序设计训练 0419