wayne 发表于 2012-1-9 12:58:37

在纸上画了一下升级过程的决策二叉树,很有规律

wayne 发表于 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) 表达

056254628 发表于 2012-1-10 09:11:38

楼上的计算公式与概率无关,必然得不到正确的结果。

zYr 发表于 2012-1-13 23:54:51

本帖最后由 zYr 于 2012-1-14 11:49 编辑

这样如何 直接模拟这个过程
void main()
{
        double n=1,k=0;        //n为实验总次数 k为实验成功(即1000次内升到九级)的次数
        int shiyan();
        double p;                        //p为概率
C:
        n++;
        int b=shiyan();       
        if (b)
        {
                k++;
        }
        p=k/n;
        cout<<p<<endl;
        goto C;
}

int shiyan()
{
        int l=1;        //l为屠龙刀等级
        int i=1;        //升级次数
        int roll();
        while(i<=1000)        //执行1000次升级操作
        {
                int r=roll();
                if (r<=3)                //30%
                {
                        l++;
                }
                else                        //70%
                {
                        if(l==1)
                        {
                                l=1;
                        }
                        else
                        {
                                l--;
                        }
                }
                if (l==9)
                {
                        break;
                }
                else
                {
                        i++;
                }
        }
        if (l==9)        //实验成功
        {
                return 1;
        }
        else                //实验失败
        {
                return 0;
        }
}

int roll()        //随机一个1到10的整数
{
        srand( (unsigned)time( NULL ) );
        int num = 1 + rand() % 10;
        return num;
/*
这个随机数的函数目前没想好
C语言不支持随机数
用时间作种子做伪随机数的话
要是程序执行得太快 1秒内就跳出了循环
随机数就一样了 会影响结果
我用上面的伪随机数代码做了一下 概率大概在0.3左右
*/
}

zYr 发表于 2012-1-14 00:11:30

电脑计算的速度确实太快了
一秒钟能做好几遍
我又试了几次概率大概在0.35附近
我觉得0.3几比较符合经验
用那么多次机会升8级应该也就这么大概率 但肯定不够精确
因为电脑会因一次随机结果给k和n都连续自加好几次 或只给n连续自加好几次
要是能改进随机数的算法就好了

zYr 发表于 2012-1-14 11:47:48

换了一下代码int roll()
{
        srand( (unsigned)time( NULL ) );
        int num = 1 + (rand() * ((int)n + (int)k) + ((int)n * (int)k)) % 10;
        return num;
}我用双核笔记本开了10个控制台同时运行
开始几分钟不知为何 十个的结果都在0.15上下浮动
后来在某一时刻后先后开始有规律地上涨 到0.3几
小数点后第二位一直浮动较大
直到大概90分钟以后才比较稳定
但小数点后第三位的变化还经常变动
为什么在运行这么长时间以后每次实验还会对概率有比较大的影响?
会不会n自加超过double型的范围了?

zYr 发表于 2012-1-14 11:52:32

有图有真相

KeyTo9_Fans 发表于 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$列就是最终结果。

KeyTo9_Fans 发表于 2012-1-14 14:51:11

zYr:

“srand(time( NULL ));”语句只能执行$1$次,不能多次执行。

由于你多次执行该语句,导致随机数质量太差,结果误差很大。

正确结果应该是$0.228556827413$。

$19#$的参考代码:#include<cstdio>
#include<memory>

double a,b,c;
int i,j,k;

void mult()
{
        for(i=0;i<9;i++)
                for(j=0;j<9;j++)
                {
                        c=0;
                        for(k=0;k<9;k++)
                                c+=a*b;
                }
        memcpy(a,c,sizeof(c));
}

void p10()
{
        memcpy(b,a,sizeof(a));
        mult();
        memcpy(b,a,sizeof(a));
        mult();
        mult();
        mult();
        mult();
}

int main()
{
        for(i=1;i<8;i++)
        {
                a=0.7;
                a=0.3;
        }
        a=0.7;
        a=0.3;
        a=1;
        p10();
        p10();
        p10();
        printf("%.12lf\n",a);
        return 0;
}输出结果:0.228556827413

wayne 发表于 2012-1-14 19:28:33

19# KeyTo9_Fans
漂亮,状态转移矩阵比递推公式的表达更简洁。
页: 1 [2] 3
查看完整版本: 屠龙刀的概率升级问题