找回密码
 欢迎注册
楼主: 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-4-26 16:34 , Processed in 0.048601 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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