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
漂亮,状态转移矩阵比递推公式的表达更简洁。