問題: 一個設計運動員打靶,靶一共10環,連開10環打中90環的可能性有多少?請用第歸演算法實現?
分析:
1)每次打靶可能的得分範圍是什嗎?
靶有10個環,那麼當打中時,分數可為1-10,如果未打中得分為0,所以每次打靶得分的範圍為0-10,共有11中可能
2)計算有多少種可能最直接的方法:
打10次靶,分別記錄這10次打靶過程,用迴圈來完成for(int i1=0;i1<=10;i++)
{
for(int i2=0;i2<=10;i2++)
{
for(int i3=0;i3<=10;i3++)
{
---
for(int i10=0;i10<=10;i10++)
{
if(i1+i2+i3+.+i10=90)
{
//一種可能
}
}
---
}
}
}
但是這樣做有兩點不足:
1)如果題目改為連打1000槍,得分為900的可能性,估計這種寫法的要哭了
2)考慮不周全,如果第一次打靶得分為0,還有9次機會,這9次機會,就要求槍槍都是滿分,如果第二槍,得分不是10,那第三槍不用打就知道可能沒有可能性了。就比如乒乓球比賽一樣,5局3勝制,如果進行了3局都是一個人勝利的話,比賽這時候就可以宣告結束。而繼續下去就是浪費時間和精力
2。採用第歸的方法來解決上述問題
第歸就是自己調自己,如果沒有結束限制的話,第歸的效果和dead loop是一樣的,但是第歸正常情況下都會有結束標誌,而且第歸的意義就在於完成迴圈層數不明確或者層數明確但是數值非常大的情形。使用它的注意點就是第歸函數肯定要具有一個或者一個以上的形參,沒有參數的第歸就形成了死迴圈。而且第歸中函數每次調用自己的時候,需要小心謹慎的控制參數。盡量防止死迴圈的產生,第歸和棧關係密切。
要實現上述功能,第歸函數要完成的功能主要有:
1)當傳入的當前打靶次數為小於1,或者大於規定次數的時候,應該退出第歸函數的執行
2)當餘下的打靶次數中每次都得滿分,但能無法達到目標分數的時候,應該退出第歸
3)如果沒有上述兩種情況,就應該執行第歸
實現代碼:
1using System;
2
3namespace Test
4{
5 /**//// <summary>
6 /// ShotScore 的摘要說明。
7 /// </summary>
8 public class ShotScore
9 {
10 //總共有多少種可能性
11 int SumRate = 0;
12 //每次可能命中的幾率範圍
13 int[] ScoreArray;
14 //總共需要多少分
15 int totalScore=0;
16 //一共能打多少次
17 int totalShot=0;
18 //當前共打中環數
19 public ShotScore(int[] sa,int ts,int t)
20 {
21 this.ScoreArray = sa;
22 this.totalShot = ts;
23 this.totalScore = t;
24 }
25 public int GetSum()
26 {
27 return SumRate;
28 }
29 public void Compute(int currentShot,int cNum)
30 {
31 //打多打少都不行
32 if(currentShot<0||currentShot>totalShot)
33 {
34 return;
35 }
36 //以後槍槍都中10都不能滿足條件,game over
37 if(((totalShot-currentShot+1)*10)<(totalScore-cNum))
38 {
39 return;
40 }
41 //打夠次數了並且總共達到了預期環數
42 if(currentShot==totalShot)
43 {
44 //這種可能性成立
45 SumRate++;
46 return;
47 }
48 for(int i=0;i<ScoreArray.Length;i++)
49 {
50 Compute(currentShot+1,cNum+ScoreArray[i]);
51 }
52
53 }
54 }
55}
56
最後結果為:92378
總結:這個問題主要考察了程式員的邏輯思考能力和對第歸函數的應用。十分簡單。但邏輯一定要清楚,分析問題的方法一定要準確。