概率:掷筛子求和, 递归,分解成子问题是面试中经常考察的问题,多看看leetcode对面试者有好处。
有一个筛子,每投一次的结果可能是1,2,3,4,5,6,每种出现的结果相同。现在给定投掷的次数n,求n次
之和是sum的概率为多少。
解析:
可以拆分成子问题,然后用递归的方式解决。
从最简单的开始分析:
n=1,sum=3, 则P(n,sum) = P(1,3)= 1/6;
n=2, sum =2, 则P(2,2)= 1/6 *1/6;可以将P(2,2)分解成P(1,1)* P(2-1,1);
n=3, sum =4, 可以分解为: P(1,1)*P(3-1,4-1) + P(1,2)*P(3-1,4-2) + P(1,3)*P(3-1,4-4),即将3次投递分解成第一次投递和剩余次数的投递,进而不断地分解,最后会分解到P(1,x);
从而一般地,P(n,sum) = P(1,x) + P(n-1,sum-x) ,其中x=1,2,3,4,5,6;
另外,计算P(n,sum)时,要判断一下是否满足,6n<=sum。
下面n>6的条件不应该加! 看后面的新代码。
#include <iostream>
using namespace std;
//n:总次数,sum:和
float cal(int n, int sum)
{
if((n<1)||(n>6))
return 0.0;
if(sum > 6*n)
{
return 0.0;
}
//递归终止条件
if( (n == 1) && (sum<=6) && (sum>=1) )
{
return 1/6.0;
}
float temp = 0.0;
for(int a=1;a<=6;a++)//第一次投掷时可能出现1-6。
{
temp =temp +( cal(1,a) * cal(n-1,sum-a) );
}
return temp;
}
int main()
{
cout << "Hello World!" << endl;
float temp = -0.1;
temp = cal(1,3);
cout<<"Probability = "<<temp<<" expected="<<1/6.0<<endl;
temp = cal(2,12);
cout<<"Probability = "<<temp<<" expected="<<1/36.0<<endl;
temp = cal(2,3);
cout<<"Probability = "<<temp<<" expected="<<2/36.0<<endl;
temp = cal(3,3);
cout<<"Probability = "<<temp<<" expected="<<1/(6*6*6.0)<<endl;
temp = cal(3,4);
cout<<"Probability = "<<temp<<" expected="<<3/(6*6*6.0)<<endl;
getchar();
return 0;
}
2020.10
#pragma once
#include <iostream>
//#include <>
class sumPosibility
{
public:
sumPosibility();
~sumPosibility();
float solve(int times, int sum) {
if (sum > 6 * times)
return 0;
if (sum < 1 * times)
return 0;
if (1 == times) {
return 1 / 6.0f;
}
float resP = 0;
//递推公式: 既分解成了子问题
resP += solve(1, 1)*solve(times - 1, sum - 1);//第一次投出了1,剩余的times-1次需要和为sum-1
resP += solve(1, 2)*solve(times - 1, sum - 2);//第一次投出了2,剩余的times-1次需要和为sum-2
resP += solve(1, 3)*solve(times - 1, sum - 3);//第一次投出了2,剩余的times-1次需要和为sum-3
resP += solve(1, 4)*solve(times - 1, sum - 4);//第一次投出了2,剩余的times-1次需要和为sum-4
resP += solve(1, 5)*solve(times - 1, sum - 5);//第一次投出了2,剩余的times-1次需要和为sum-5
resP += solve(1, 6)*solve(times - 1, sum - 6);//第一次投出了2,剩余的times-1次需要和为sum-6
return resP;
}
float Test1() {
}
};
int main() {
sumPosibility obj;
std::cout << obj.solve(1, 0) << " expected=" << 0 << " \n";
std::cout << obj.solve(1, 1) << " expected=" << 1/6.0f << " \n";
std::cout << obj.solve(1, 6) << " expected=" << 1 / 6.0f << " \n";
std::cout << obj.solve(2, 3) << " expected=" << 1 / 18.0f << " \n";
std::cout << obj.solve(3, 3) << " expected=" << 1 / 1 / (6 * 6 * 6.0) << " \n";
std::cout << obj.solve(3, 4) << " expected=" << 3 / 1 / (6 * 6 * 6.0) << " \n";
std::cout << obj.solve(7, 7) << " expected=" << 1 / (6 * 6 * 6.0* 6 * 6 * 6.0*6.0) << " \n";
return 0;
}