有两种解法:
一、递归求出所有的可能性,然后计算概率。
二、递归过程需要重复计算,所以可以用数组来存储结果提升速度。
下面代码有两种方式并可以看出时间的差异。
#include<iostream>
#include<string.h>
#include<cmath>
#include<time.h>
using namespace std;
void basegetdicechance(int *totalsum,int current,int sum,int k){
if(current == 0){
++totalsum[sum-k];
return;
}
for(int i =1;i<=6;++i){
basegetdicechance(totalsum,current-1,sum+i,k);
}
}
int main(){
int k;
clock_t start,end;
printf("获得骰子的个数:\n");
scanf("%d",&k);
int *totalsum = (int *)malloc(sizeof(int)*(5*k+1));
for(int i =0;i<=5*k;++i)
totalsum[i] = 0;
start = clock();
double sumchance = pow(6.0,(double)k);
basegetdicechance(totalsum,k,0,k);
for(int i =0;i<=5*k;++i){
printf("基本方法:和为%d的概率出现为百分之%f\n",i+k,(double)totalsum[i]*100/sumchance);
}
end = clock();
printf("基本方法所需时间为%f\n",(double)(end-start)/CLOCKS_PER_SEC);
free(totalsum);
//快速的方法
int *totaltwosum[2];
totaltwosum[0] = (int *)malloc(sizeof(int)*(6*k+1));
totaltwosum[1] = (int *)malloc(sizeof(int)*(6*k+1));
for(int i =0;i<=6*k;++i){
totaltwosum[0][i] =0;
totaltwosum[1][i] =0;
}
start = clock();
int flag = 0;
for(int i =1;i<=6;++i)
totaltwosum[flag][i] = 1;
for(int j =2;j<=k;j++){
for(int i = 0;i<j;++i)
totaltwosum[1-flag][i] =0;
for(int sum =j;sum <=6*j;sum++){
totaltwosum[1-flag][sum] = 0;
for(int i = 1;i<=sum&&i<=6;++i)
totaltwosum[1-flag][sum] += totaltwosum[flag][sum-i];
}
flag = 1-flag;
}
for(int i =k;i<=6*k;++i){
printf("快速方法:和为%d的概率出现为百分之%f\n",i,(double)totaltwosum[flag][i]*100/sumchance);
}
end = clock();
printf("快速方法所需时间为%f\n",(double)(end-start)/CLOCKS_PER_SEC);
system("PAUSE");
return 0;
}
约瑟夫环,比较简单的问题了,用链表来解。
#include<iostream>
#include<list>
using namespace std;
int getlastone_list(unsigned int n,unsigned int m){
list<int> jopher;
for(int i =0;i<n;++i)
jopher.push_back(i);
list<int>::iterator current = jopher.begin();
while(jopher.size()>1){
for(int i =1;i<m;++i){
++current;
if(current == jopher.end())
current = jopher.begin();
}
printf(" %d",*current);
current = jopher.erase(current);
if(current == jopher.end())
current = jopher.begin();
/*这里涉及erase之后迭代器失效,而erase方法会返回下个迭代器*/
}
printf("\n");
return *current;
}
int main(){
printf("输人n和m:\n");
unsigned int n,m;
scanf("%d%d",&n,&m);
int result = getlastone_list(n,m);
printf("最后出来的是%d",result);
system("PAUSE");
return 0;
}
至于另外一种O(n)的更复杂方法,数学证明比较难。略。