递归方法

问题描述

一个射击运动员打靶,每轮射击最高得分10环。问连续10轮总分正好90环的可能性有多少种?

不考虑运动员的技术因素,即认为相邻两次射击是不相关的,且任何得分都是可能发生的。

 

问题分析

1、每轮得分共有11种情况,0-10

2、采用逆向分析,假设10轮射击已经完毕,每轮得分分别为score[9],score[8],...,score[0],

先考虑第10轮和前面9轮的递归关系

假设第10轮得分为i, 0<=i<=10

则前面9轮得分总和必须为90-i,,90-i=score[8]+...+score[0]

假设第9轮得分为j, 0<=j<=10

则前面8轮得分总和必须为90-i-j,,90-i-j=score[7]+...+score[0]

...

因此,递归关系用到的两个参数是“第N轮”和“第N轮打完应得的总分数”

 

 

代码实现

 

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using std::cout;
using std::endl;

unsigned int score[10] = {0};
unsigned int sum = 0;
void Output()//在满足条件时调用,察看每轮打靶分数
{
 for (int i = 0;i < 10;++i)
  cout << score[i] << " ";
 cout <<endl;
 sum++;
}
/* 利用排列组合,共有11的10次方种可能。
 递归查找
*/
void Find_s(unsigned int round/*第N轮*/,unsigned int total/*第N轮打完应得分数*/)
{
 if (total > (round+1)*10 || total < 0)//C语言0下标开始,所以round+1
 {
  //cout << "impossible caught. "<<endl;
  return;
 }
 if (0==round)//回退到第一轮,成功找到
 {
  score[0] = total;
  Output();
  return;
 }
 for (int i = 0;i <=10;++i)
 {
  score[round] = i;
  Find_s(round-1,total-i);
 }
}

int _tmain(int argc, _TCHAR* argv[])
{
 DWORD dwStart = GetTickCount();
 Find_s(9,90);
 DWORD dwEnd =GetTickCount();

 cout << "total possible " << sum << "running time" << (dwEnd-dwStart)<<endl;

 return 0;
}

 

 

问题延伸

一个射击运动员打靶,每轮射击最高得分10环。问连续10轮总分不少于90环的可能性有多少种?

不考虑运动员的技术因素,即认为相邻两次射击是不相关的,且任何得分都是可能发生的。

 

问题分析

整个问题分析的过程相同,不同的是total的含义改变,应该是“第N轮打完应得分数的下限”

 

代码实现

void Find_s(unsigned int round/*第N轮*/,unsigned int total/*第N轮打完应得分数的下限*/)

{

...

 if (0==round)//回退到第一轮,成功找到
 {

for(unsigned int k = total;k <= 10;++k){
  score[0] = k;
  Output();

}
  return;
 }

...

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值