射击运动员打靶
来源:互联网 发布:房地产经纪人网络教育 编辑:程序博客网 时间:2024/04/28 18:43
偶尔看到个题,一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能性有多少种?要求用递归算法解决。
递归求解是很自然的一种思路:
m枪打中n环,s(m,n)对应其射击方案
对第一枪有0-10环10种选择,假定为k环,然后对剩下的m-1枪,很显然s(m-1,n-k)对应其射击方案
因此:
很容易写一个对应的Java程序,输出射击方案
import java.util.Arrays;public class ShootingPlan {static int count = 0;static int numberOfShooting = 10;static int totalScore = 90;public static void main(String[] args) {//score数组表示一个射击计划,score[i]表示第i枪的环数int [] score = new int[numberOfShooting];Arrays.fill(score, 0);long beginTime = System.currentTimeMillis();shootplan(numberOfShooting, totalScore, score);long endTime = System.currentTimeMillis();System.out.println("Executed in " + (endTime - beginTime) + " milliseconds");}/**计算一个射击计划 * @param number 射击次数 * @param total 总环数 * @param score 记录成绩的数组 */private static void shootplan(int number, int total, int[] score) {// 边界条件,如果仅剩一枪且剩余环数符合条件,那剩余环数即为最后一枪的成绩,同时打印输出10枪成绩if(number == 1 && total <= 10 && total >= 0) {score[numberOfShooting - number] = total; // 输出一个射击计划 System.out.print(++count + ":");for(int i : score) System.out.print(i + " ");System.out.println();}if(number > 1) {for(int i = 0; i <= 10; i++) {score[numberOfShooting - number] = i;shootplan(number - 1, total - i, score);}}}}
运行结果最后几行如下
当然,上面这个实现谈不上什么效率,是指数级的算法:(
可以看到执行时间是18.483秒
尝试优化算法
1.考虑减小搜索空间——在递归计算中,当S(i,k)的k>10*i时,可以终止搜索,因为成绩超出上限,枪枪靶心也game over……
改进后的方法及运行结果
/**计算一个射击计划 * @param number 射击次数 * @param total 总环数 * @param score 记录成绩的数组 */private static void shootplan(int number, int total, int[] score) {// 边界条件,如果仅剩一枪且剩余环数符合条件,那剩余环数即为最后一枪的成绩,同时打印输出10枪成绩if(number == 1 && total <= 10 && total >= 0) {score[numberOfShooting - number] = total; // 输出一个射击计划 System.out.print(++count + ":");for(int i : score) System.out.print(i + " ");System.out.println();}// 减小搜索空间if(total > number * 10)return;if(number > 1) {for(int i = 0; i <= 10; i++) {score[numberOfShooting - number] = i;shootplan(number - 1, total - i, score);}}}
还是有明显差异的
2.是否可以借鉴动态规划算法,存储计算过的子结构以空间换时间?
感觉上是靠谱的,但这个空间开销貌似有点惊艳…… 找机会试试
下面重头戏,能不能直接计算出方案总数? (不战而屈人之兵自然爽,总不能每次都傻傻跑段代码给出结果)
重新整理下需求——10枪打90环的方案数
用组合数学里的一一对应思想转化下,考虑补集——每枪少打的环数xi'
即关注每一枪比10环少的环数,10枪打90环 等价于10枪共少打10环,那么每枪少几环的方案数和原方案数一一对应
把总共少打的10环分配到10枪中,相当于把10个球放到10个不同的盒子里,盒子可以为空
熟悉组合数学的朋友可以一眼看出,这是允许重复的组合,结果数为C(10+10-1,10) = C(19,10) = 92378
或者用隔板法考虑,把10个球放到10个不同的盒子里,盒子可以为空,等价于把10个球分成10堆
需要9个隔板,把球和隔板的位置一字排开,结果数为C(19,10)或者C(19,9) = 92378
进一步考虑,m枪打n环,如果 n>= 10m - 10,那么总的方案数为 C(10m-n+9, 9)
如果n< 10m - 10,这时候miss的环数大于10了,不能再放到一枪中了,上述公式不再适用……
- 射击运动员打靶
- 运动员打靶问题
- 运动员打靶问题
- 打靶问题 一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能行有多少种?
- 打靶问题。一个射击运动员打靶,靶一共有10环,连开10 枪打中90环的可能性有多少?
- 打靶问题 一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能行有多少种?
- 打靶问题。一个射击运动员打靶,靶一共有10环,连开10 枪打中90环的可能性有多少?
- 面试题83:运动员打靶
- 一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能性有多少种?(递归算法)
- 面试题:一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能性有多少种?请用递归算
- 面试经典(12)--射击打靶问题
- 打靶
- 打靶
- 算法设计与分析题目练习一:运动员打靶(递归算法)
- 射击运动员10枪打90环的打发有多少种
- 分享:射击运动员10发打中90环有多少种可能?(C#)
- 打靶归来
- 打靶问题
- js整数,小数转换
- Jquery EasyUI后台实例
- 大佬们看2013互联网走势
- Linux 常用命令
- 高手的C++学习忠告,虚心学习下~~
- 射击运动员打靶
- Windows下安装Redmine
- Struts2声明式异常
- stagefright 架构分析(三) stagefright 功能和调用流程
- AIF Operation -- Find()
- 善用VS中的Code Snippet来提高开发效率
- libnet入门
- 为什么要保持代码整洁------初读<<代码整洁之道>>
- tcpdump命令详解