找回密码
 欢迎注册
楼主: wayne

[分享] 屠龙刀的概率升级问题

[复制链接]
 楼主| 发表于 2012-1-9 12:58:37 | 显示全部楼层
在纸上画了一下升级过程的决策二叉树,很有规律
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-1-9 16:29:35 | 显示全部楼层
10# 056254628 设g(n,m) 表示经过n次升级后级别为m的所有可能情况, 升级到9级将停止尝试升级。 则
g(n,1)=g(n-1,2)+g(n-1,1) g(n,9)=g(n-1,8) g(n,8)=g(n-1,7) g(n,k)=g(n-1,k-1)+g(n-1,k+1)
可以算出,n次升级后,仍然停留在1级的情况有 g(n,1) = C(n,floor(n/2)) 种 ,然后所有的情况都可以用g(n,1) 表达
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-1-10 09:11:38 | 显示全部楼层
楼上的计算公式与概率无关,必然得不到正确的结果。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-1-13 23:54:51 | 显示全部楼层
本帖最后由 zYr 于 2012-1-14 11:49 编辑 这样如何 直接模拟这个过程
  1. void main()
  2. {
  3. double n=1,k=0; //n为实验总次数 k为实验成功(即1000次内升到九级)的次数
  4. int shiyan();
  5. double p; //p为概率
  6. C:
  7. n++;
  8. int b=shiyan();
  9. if (b)
  10. {
  11. k++;
  12. }
  13. p=k/n;
  14. cout<<p<<endl;
  15. goto C;
  16. }
  17. int shiyan()
  18. {
  19. int l=1; //l为屠龙刀等级
  20. int i=1; //升级次数
  21. int roll();
  22. while(i<=1000) //执行1000次升级操作
  23. {
  24. int r=roll();
  25. if (r<=3) //30%
  26. {
  27. l++;
  28. }
  29. else //70%
  30. {
  31. if(l==1)
  32. {
  33. l=1;
  34. }
  35. else
  36. {
  37. l--;
  38. }
  39. }
  40. if (l==9)
  41. {
  42. break;
  43. }
  44. else
  45. {
  46. i++;
  47. }
  48. }
  49. if (l==9) //实验成功
  50. {
  51. return 1;
  52. }
  53. else //实验失败
  54. {
  55. return 0;
  56. }
  57. }
  58. int roll() //随机一个1到10的整数
  59. {
  60. srand( (unsigned)time( NULL ) );
  61. int num = 1 + rand() % 10;
  62. return num;
  63. /*
  64. 这个随机数的函数目前没想好
  65. C语言不支持随机数
  66. 用时间作种子做伪随机数的话
  67. 要是程序执行得太快 1秒内就跳出了循环
  68. 随机数就一样了 会影响结果
  69. 我用上面的伪随机数代码做了一下 概率大概在0.3左右
  70. */
  71. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-1-14 00:11:30 | 显示全部楼层
电脑计算的速度确实太快了 一秒钟能做好几遍 我又试了几次概率大概在0.35附近 我觉得0.3几比较符合经验 用那么多次机会升8级应该也就这么大概率 但肯定不够精确 因为电脑会因一次随机结果给k和n都连续自加好几次 或只给n连续自加好几次 要是能改进随机数的算法就好了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-1-14 11:47:48 | 显示全部楼层
换了一下代码
  1. int roll()
  2. {
  3. srand( (unsigned)time( NULL ) );
  4. int num = 1 + (rand() * ((int)n + (int)k) + ((int)n * (int)k)) % 10;
  5. return num;
  6. }
复制代码
我用双核笔记本开了10个控制台同时运行 开始几分钟不知为何 十个的结果都在0.15上下浮动 后来在某一时刻后先后开始有规律地上涨 到0.3几 小数点后第二位一直浮动较大 直到大概90分钟以后才比较稳定 但小数点后第三位的变化还经常变动 为什么在运行这么长时间以后每次实验还会对概率有比较大的影响? 会不会n自加超过double型的范围了?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-1-14 11:52:32 | 显示全部楼层
有图有真相
90+.JPG
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-1-14 13:58:02 | 显示全部楼层
设矩阵$A=[(0.7,0.3,0,0,0,0,0,0,0),(0.7,0,0.3,0,0,0,0,0,0),(0,0.7,0,0.3,0,0,0,0,0),(0,0,0.7,0,0.3,0,0,0,0),(0,0,0,0.7,0,0.3,0,0,0),(0,0,0,0,0.7,0,0.3,0,0),(0,0,0,0,0,0.7,0,0.3,0),(0,0,0,0,0,0,0.7,0,0.3),(0,0,0,0,0,0,0,0,1)]$, 然后计算$A^1000$,结果记为$P$。 即$P=A^1000$。 然后取$P$的第$1$行第$9$列就是最终结果。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-1-14 14:51:11 | 显示全部楼层
zYr: “srand(time( NULL ));”语句只能执行$1$次,不能多次执行。 由于你多次执行该语句,导致随机数质量太差,结果误差很大。 正确结果应该是$0.228556827413$。 $19#$的参考代码:
  1. #include<cstdio>
  2. #include<memory>
  3. double a[9][9],b[9][9],c[9][9];
  4. int i,j,k;
  5. void mult()
  6. {
  7. for(i=0;i<9;i++)
  8. for(j=0;j<9;j++)
  9. {
  10. c[i][j]=0;
  11. for(k=0;k<9;k++)
  12. c[i][j]+=a[i][k]*b[k][j];
  13. }
  14. memcpy(a,c,sizeof(c));
  15. }
  16. void p10()
  17. {
  18. memcpy(b,a,sizeof(a));
  19. mult();
  20. memcpy(b,a,sizeof(a));
  21. mult();
  22. mult();
  23. mult();
  24. mult();
  25. }
  26. int main()
  27. {
  28. for(i=1;i<8;i++)
  29. {
  30. a[i][i-1]=0.7;
  31. a[i][i+1]=0.3;
  32. }
  33. a[0][0]=0.7;
  34. a[0][1]=0.3;
  35. a[8][8]=1;
  36. p10();
  37. p10();
  38. p10();
  39. printf("%.12lf\n",a[0][8]);
  40. return 0;
  41. }
复制代码
输出结果:
  1. 0.228556827413
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2012-1-14 19:28:33 | 显示全部楼层
19# KeyTo9_Fans 漂亮,状态转移矩阵比递推公式的表达更简洁。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-23 02:33 , Processed in 0.027960 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表