<delect id="sj01t"></delect>
  1. <em id="sj01t"><label id="sj01t"></label></em>
  2. <div id="sj01t"></div>
    1. <em id="sj01t"></em>

            <div id="sj01t"></div>
            等級考試

            一個組合數的求解方法

            時間:2025-05-13 10:46:59 等級考試 我要投稿
            • 相關推薦

            一個組合數的求解方法

              有從10個不同的數中取出7個,如何求出所有組合?
              初看這個問題,確實不太好下手,雖然我們理解這個問題很容易,但要讓計算機“理解”可得花點功夫了。
              先分析:首先想到,如果由10個元素中的7個組成一個序列,并且這7個元素互不相等,這就比較接近于正解了;然后考慮,組合中7元素是不分先后的,我們如何剔除多余的數據呢(如四選二中(1,3)與(3,1)是相同解)?
              我們可以在編程時作一種限定,7個元素的排列順序滿足我們的一個規定,這樣,就可以依據相同位置的值不能相同來排除不正確的解。
              這樣我們的第一個解呼之欲出了:可以利用數組來進行選取,不同的數組下標順序就代表了不同的解,而且我們約定這個下標序列必須是升序,這就利于我們排除冗余值。
              在本文中,約定這10個數是如下形式的數組,并且已經賦值。計算的結果在一個TMemo控件中顯示。
              var
              Value:array[1..10] of integer;
              解法一、
              按鈕1的點擊事件處理。
              procedure TForm1.Button1Click(Sender: TObject);
              var
              idx1,idx2,idx3,idx4,idx5,idx6,idx7: integer;
              tmpStr:string;
              begin
              Memo1.Lines.Clear;
              for idx1:=1 to 4 do
              for idx2:=idx1+1 to 5 do
              for idx3:=idx2+1 to 6 do
              for idx4:=idx3+1 to 7 do
              for idx5:=idx4+1 to 8 do
              for idx6:=idx5+1 to 9 do
              for idx7:=idx6+1 to 10 do
              begin
              tmpStr:=IntToStr(idx1)+' '+IntToStr(idx2)+' '+IntToStr(idx3)
              +' '+IntToStr(idx4)+' '+IntToStr(idx5)+' '+IntToStr(idx6)
              +' '+IntToStr(idx7) ;
              Memo1.Lines.Add(tmpStr);
              end;
              end;
              解中只顯示了下標的組合,實際應用把下標改為Value數組即可:tmpStr:=IntToStr(Value[idx1])+' '+IntToStr(Value[idx2])+...; 。
              這個解的一個亮點就是每一個循環變量的初值都是它前一個變量加1;這就保證后一個下標一定不等于前一個下標,請體會一下為什么循環控制變量的終值為4~10。
              解法二、
              中學的數學教材中就講到C(10,7)=C(10,3),這個很好理解,從10中選7,剩下3個,所有選七的組合完成,也就是所有選三的組合完成,反之亦然。
              按鈕2的點擊事件處理:
              procedure TForm1.Button2Click(Sender: TObject);
              var
              idx1,idx2,idx3,idx4: integer;
              tmpStr:string;
              begin
              Memo1.Lines.Clear;
              for idx1:=1 to 8 do
              for idx2:=idx1+1 to 9 do
              for idx3:=idx2+1 to 10 do
              begin
              tmpStr:='';
              for idx4:=1 to 10 do
              if (idx4<>idx1) and (idx4<>idx2) and (idx4<>idx3) // 加入一個元素
              then tmpStr:=tmpStr+IntToStr(Value[idx4])+' ';
              Memo1.Lines.Add(tmpStr);
              end;
              end;
              這個解是十選三,然后顯示剩下的七個,是不是有點意思呢?
              以上加入元素的判斷可以改寫為:
              if ((idx1+100)*(idx2+100)*(idx3+100) mod (idx4+100) >0 )
              請體會一下同余理論的運用,這里利用了101到110這十個數中任一個數都不被其它三個數的乘積整除的特性
              解法三、
              以上兩解也可用集合來實現。
              再想想,以上兩解都是用了多重循環,必須定義多個循環變量,通用性似乎差了點。
              觀察這些循環(尤其是解一),形式是何等的一致!
              也許諸位已經想到我要用遞歸調用來解決這個問題了。
              要設計遞歸,首先要確定哪些變量是必須向這個函數傳遞的,容易知道,調用時要知道當前元素的起始下標與終止下標,當然還有兩個必不可少的參數就是我這個函數計算的是從多少選多少的,這樣就確定了四個參數。
              還有一個要注意的地方,是遞歸何時顯示數據?顯然應當在求最后一個元素時。
              (關于遞歸調用的一些詳細的論述,可以參看喬林的《參透Delphi/Kylix》一書或其它教材)
              請看實現:
              全局變量
              var
              GIDX:array[1..20] of integer; // 記錄下標的數組。
              procedure MyRecur(Total,SelCnt,BLoc,ELoc:integer);
              var
              idx,jjj:integer;
              tmpStr:string;
              begin
              if (ELoc=Total) // 終止狀態
              then begin
              for idx:=BLoc to ELoc do
              begin
              GIDX[SelCnt+ELoc-Total]:=idx; // 注意此處應與下面 8888處一致
              tmpStr:='';
              for jjj:=1 to SelCnt do tmpStr:=tmpStr+IntToStr(Value[GIDX[jjj]])+' ';
              Form1.Memo1.Lines.Add(tmpStr);
              end;
              end
              else begin
              for idx:=BLoc to ELoc do
              begin
              GIDX[SelCnt+ELoc-Total]:=idx; // 8888
              MyRecur(Total,SelCnt,idx+1,ELoc+1);
              end;
              end;
              end;
              procedure SelNumber(Total,SelCnt:integer);
              begin
              if (Total<1) or (Total<SELCNT)< p> 
              then begin
              ShowMessage('數據不正確!');
              Exit;
              end;
              MyRecur(Total,SelCnt,1,Total-SelCnt+1);  // 最初第三個參數總為1
              end;
              使用:
              procedure TForm1.Button3Click(Sender: TObject);
              var
              ttl,sel:integer;
              begin
              Memo1.Clear;
              ttl:=StrToInt(Edit1.Text);  // 請自己加上對TEdit的容錯處理。
              sel:=StrToInt(Edit2.Text);
              SelNumber(ttl,sel);
              end;
              好了,在Edit1中輸入‘100’,在Edit2中輸入'3',執行試試,三十多萬行的數據不斷地滾出來了吧。
              建議在計算前先估算一下共多少組合,最好不要超過10萬。
            相關推薦:
            經濟師資格證
            2013年經濟師考試時間
            可不參加職稱外語考試的條件
            廣州2013年職稱英語考試報名
            大專生怎獲取學位、報考研究生
            跨國公司需要考取那些證書
             

            【一個組合數的求解方法】相關文章:

            java集合數組的區別08-17

            質數和合數教學設計11-02

            java集合數組的輸出辦法07-31

            《質數和合數》數學教案09-30

            關于java集合數組的區別08-03

            C語言遞歸函數的執行與求解08-11

            小升初數學專項復習之質數與合數06-07

            2017年俄語備考集合數詞11-05

            加減混合數學教案設計08-10

            <delect id="sj01t"></delect>
            1. <em id="sj01t"><label id="sj01t"></label></em>
            2. <div id="sj01t"></div>
              1. <em id="sj01t"></em>

                      <div id="sj01t"></div>
                      黄色视频在线观看