发表评论
两点疑问:
1 为什么不直接用概率公式算呢?这样最快
2 10环和1环的打中概率不一样吧?
#2楼[
楼主]2007-02-01 16:04 |
@Dflying Chen
不是概率,是求出全部的可能性
2 10环和1环的打中概率不一样吧?
现实中的确概率不一样,如果考虑概率的问题,估计这就麻烦了,题目中没有说那环命中几率,估计应该查看的不是概率问题
#3楼[
楼主]2007-02-01 16:07 |
@Dflying Chen
另外,偷偷告诉老兄,小弟数学门门不及格,概率是抄人家的才勉强得70的。所以数学公式,我一个都没记住。唉,真应该学学高数,线代,概率,复变,模糊数学啥的了,都学过,都忘了。
#5楼[
楼主]2007-02-01 16:29 |
@韦恩卑鄙
您提醒一下,用哪个数学公式能处理这个问题
说是求"可能性"不妥当吧, 应该是求"得90环可能的排列种数"
概率问题,就不应该如此用计算机去求解。
抛开大学的概率课程不说,懂得排列组合的就可以算,或许因此楼上说高中公式就能解决。其实公式用了并不代表你懂得严密的概率理论,只是每个人从小心中默认“等概率事件”的定义而已。如此说来,这种题小规模数量级在小学奥数题中出得不少,是不是应该说聪明的小学生都应该懂?
@Adrian.H
这种可能性问题本来就是通过求排列组合获得的,因为我们假设了某些东西为等概率事件。例如再复杂组合的硬币投掷问题,我们都假设一个硬币正面出现和反面出现是等概率事件,而历史上确实有人去投了上万次硬币证明这一点。
@Cat Chen
但打中每个环数的概率是不一样的, 假设击中盘中任意一处的概率是相等的, 那么打中任何一环的概率为{环的面积/盘面的面积}, 很显然, 环的面积和环的得分不是成正比的.
那么, 同样是90分的情况:
例如一种是: 9 9 9 9 9 9 9 9 9 9
另一种是: 9 9 9 9 9 9 9 9 10 8
它们的概率不相等. 后面一种的理论概率更大((9^2)*2 < (10^2 + 8^2)).
So, 对于这个问题, 每种得分的每种情况不是一定等概率的.
所以我说题目使用"可能性"这个词欠妥. 排列的种数不能代表"得到90分的概率"
就计算机实现而言,在.NET里面我不知道怎么实现,Random类提供的是伪随机函数.
图明显画错了......
"是否打够次数"没有"是"分支,其他的错误就懒得看了,感觉很乱......
#11楼[
楼主]2007-02-01 19:45 |
修改了一下
程序大的逻辑基本算对的,但第42行有错误,应该为
42 if(cNum>=totalScore) //总分>需要分数
按照楼主"不可能打到就休息"的理论,提前打满了也不需要泄愤,所以没有
currentShot==totalShot的条件
另外,应该增加一个失败次数公共字段,来计算失败次数,因为总的可能性不是10000!!!
最后才能得到可能性
#13楼[
楼主]2007-02-01 20:14 |
@目标年薪三千万
您再仔细调试一下吧,程序肯定是对的。不是说if(cNum>=totalScore)的时候才认为可能情况+1,而是只要我判断最后一次我只要能满足目标分数,不管最后一次多少分,0分也可以,10分也可以。
这个判断在
//以后枪枪都中10都不能满足条件,game over
37 if(((totalShot-currentShot+1)*10)<(totalScore-cNum))
38 {
39 return;
40 }
所谓的game over不是整个第归都结束了,而是对每次尝试的结束。
仍然要做其它不同类新的尝试
#14楼[
楼主]2007-02-01 20:16 |
也就是说执行到
37 if(((totalShot-currentShot+1)*10)<(totalScore-cNum))
38 {
39 return;
40 }
没有return,并且currentShot=10的时候,那这就是一种可能了
#15楼[
楼主]2007-02-01 20:19 |
@目标年薪三千万
感觉你还是对第归认识不够清楚,第归终的return只是结束掉本次函数调用而已
@Adrian.
对哦,那么这个真的是简单的排列组合问题,连概率论都不需要用到。
“使用它的注意点就是第归函数肯定要具有一个或者一个以上的形参,没有参数的第归就形成了死循环。”——其实这个不一定要是型参,全局变量或者类成员变量也可以。
事实上,所有的递归都可以用递推写,这样能够更有效防止栈溢出。
@jillzhang
那么,请问
1.请走一遍逻辑,为了简便,假设只要开1枪,5环算成功.
2.根据"不可能打到就不用再打"的理论,那么,如果提前达到了目标,也就不用打了,比如10次打90环,前9次就已经打到,那么第10次呢,应该不用打,也就是说,这是一次情况,而不是10次情况.
#18楼[
楼主]2007-02-02 08:11 |
1.请走一遍逻辑,为了简便,假设只要开1枪,5环算成功.
这种可能性只有一种
首先传递1,0
1)既没有打多也没有打少
2)以后都打中,会超过总分
3)当前次数为要求次数,可能性+1,第归不执行,退出
-------------------------------------------
2.你第二个问题,你说的是一种可能,但还有其它可能,最后一枪必须打中0-10环,所以,最后一枪就有11种可能
#19楼[
楼主]2007-02-02 08:56 |
其实这个问题就是简单的排列组合问题,给他的用第归算法限制住了,还好兄弟们眼光犀利,多谢大家
其实这个问题和10个苹果,分给10个人,一共有多少种分法是一模一样的
@jillzhang
我就不知道题目的意义了,究竟是正好打中目标环数算成功呢,还是超过目标环数也算成功?
你第一个问题和第二个问题的回答貌似本身在这个问题上矛盾了.
如果算超过的,那么第一个问题就有5,6,7,8,9,10六种情况,而不是1种!
如果不算超过的,那么第二个问题只有一种情况,而不是11种!
但你的程序中很明显是超过目标分数,还要开枪的算法.
如果无论如何都要开满需要的枪数,那么这道题目是和分苹果,执筛子无异,那么
总的次数=总枪数*Count(可能环数)
但楼主说的"怎么打都不够分数,就不用浪费时间打(多种情况只算一次)"的逻辑,这就完全不一样了.
这问题可以如下:
如果有10个变量x1,x2,......,x9,x10,并且其和为90,即x1+x2+.....+x9+x10=90,每个变量是0<=x<=10。
试列出每种组合!
既然说到算法,那就得考虑内存和运行时间,一般这样的题目在ACM上要求是运行时间为1s,内存为64M,CPU也不能太好,800Mhz吧
#25楼[
楼主]2007-02-02 13:17 |
@目标年薪三千万
你还是没明白,不是每次都必须打完的亚
比如你第一枪0分,第二枪你打0-9分,程序退出这次第一枪0分的尝试,换成第一枪1分的尝试啦,如果继续的话,就和你说的必须打够了才行,但关键是以后都得满分都不能达标的话,你就不用打了,新一轮比赛就可以了
呵呵,好像大家讨论远了,博主只是为了说明递归算法,而大家倒计较起来概率了。
我个人更侧重于递归函数的实现。
static void Main(string[] args)
{
int Count = 10; // 次数
int Per = 10; // 最大环数,就是最大有10环
int Total = 90; // 要求得分9
Console.WriteLine("可能性:{0}%", (Double)run(Per, Count, Total) * 100 / Math.Pow(Per, Count));
Console.ReadKey();
}
/// <summary>
/// 计算打靶ii次,得分rr的可能性,最大环数kk
/// </summary>
static int run(int kk, int ii, int rr)
{
if (ii < 1 && rr == 0) return 1;
// 参数不正确
if (ii < 1) return 0;
// 就算全部打中,都赢不了的,剔除
if (ii * kk < rr) return 0;
// 全部打中才能得到这个分数,只有一种可能
if (ii * kk == rr) return 1;
int rs = 0;
// 本次打靶有kk+1种可能
for (int i = 0; i <= kk; i++)
{
// 计算ii-1次打靶,得到分数rr-i的可能
rs += run(kk, ii - 1, rr - i);
}
return rs;
}
我的程序,跟楼主的运行结果一样:
--------------------------------------------------------
#define TIMES 10//总共打10次
#include <stdio.h>
int counts=0;//打中90环的次数
void shot(int sum,int times)
{
if ((10 * (TIMES - times + 1)) >= sum)
{
if (times > 10)
return;
for (int i=0; i<=10; i++)
{
if ((sum-i) == 0)
{
counts ++;
}
else if ((sum-i) > 0)
shot(sum-i,times+1);
}
}
}
void main()
{
shot(90,1);
printf("%d\n", counts);
}
甲四次打靶分数为:“10、7、7、6”。
乙四次打靶分数为:“9、8、7、6”。
问甲乙谁赢了???
不知道你的currentshot在什么情况下才等于totalshot,
是不是在你的递归调用中只有可能当打够10次后,并且满足90环条件下才可能,同时此时也就会推出递归循环。
而这种情况在你的递归中出现的次数应该是只有一次。
但你的sumrate只有在这种情况下才加1, 也就是你的递归结果应该是1