VFP 愛用者社區 首頁 VFP 愛用者社區
本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入

遞迴函數的應用--組合求解之應用1

 
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區
上一篇主題 :: 下一篇主題  
發表人 內容
朱育興



註冊時間: 2003-08-25
文章: 661
來自: 台中市大里區

第 1 樓

發表發表於: 星期六 十二月 20, 2003 2:59 pm    文章主題: 遞迴函數的應用--組合求解之應用1 引言回覆

* 這是動感游標論壇的「智力比拚」所出的題目
* 為求排版美觀,空白為全形空白,若要測試請將全形空白改為半形空白


* -------------------------------------------------- *
* 題目:某鐵路上共有10個車站,問需要準備幾種車票?
* 1.類似這種問題,我曾發表過 3 篇,我把它稱之為
*  「遞迴函數的應用」
* 2.這個問題我是參考我的「遞迴函數的應用」之第一篇的
*  組合求解改寫的
* 2003.12.20 YSC E-MAIL: y5096@ms23.hinet.net
* -------------------------------------------------- *

CLEAR ALL
CLOSE ALL
M_cSetEscape = SET("ESCAPE")
SET ESCAPE OFF
__Esc  = .F.
__IsCalc = .F. && 是否正在計算中
M_nTran = "99,999,999,999,999,999,999,999,999,999"
WW_oMESSAGEBOX = CREATEOBJECT("UserForm1")
WITH WW_oMESSAGEBOX
 .spinNum.Value = 10
 .Show
ENDWITH
IF VARTYPE(WW_oMESSAGEBOX) = "O"
IF !ISNULL(WW_oMESSAGEBOX)
 WW_oMESSAGEBOX.Release
ENDIF
ENDIF
SET ESCAPE &M_cSetEscape
CLEAR ALL
CLOSE ALL
RETURN

* ---------- DEFINE CLASS ---------- *
DEFINE CLASS UserForm1 AS Form
 AutoCenter  = .T.
 BackColor   = RGB(0,128,192)
 BorderStyle  = 3
 Closable   = .F.
 DoCreate   = .T.
 FontName   = "細明體"
 FontSize   = 12
 ForeColor   = RGB(255,255,255)
 KeyPreview  = .T.
 MaxButton   = .F.
 MinButton   = .F.
 ShowTips   = .T.
 ShowWindow  = 1
 Top      = 100
 WindowState  = 0
 WindowType  = 1
 Width     = 450
 Height    = 165
 Caption    = "鐵路上共有 N 個車站"

 ADD OBJECT (SYS(2015)) AS LABEL WITH;
  AutoSize   = .T.,;
  BackStyle   =  0,;
  Caption    = "請輸入共有",;
  ForeColor   = RGB(255,255,255),;
  FontName   = "細明體",;
  FontSize   = 12,;
  Left     = 15,;
  Top      = 27

ADD OBJECT spinNum AS SPINNER WITH;
  FontName     = "細明體",;
  FontSize     = 11,;
  Format      = "RK",;
  Height      = 23,;
  InputMask     = "99",;
  KeyboardHighvalue = 99,;
  KeyboardLowvalue =  2,;
  Left       = 100,;
  SpinnerHighvalue = 99,;
  SpinnerLowvalue  =  2,;
  Top        = 25,;
  Width       = 60

 ADD OBJECT (SYS(2015)) AS LABEL WITH;
  AutoSize   = .T.,;
  BackStyle   =  0,;
  Caption    = "個車站",;
  ForeColor   = RGB(255,255,255),;
  FontName   = "細明體",;
  FontSize   = 12,;
  Left     = 165,;
  Top      = 27

 ADD OBJECT (SYS(2015)) AS LABEL WITH;
  AutoSize   = .T.,;
  BackStyle   =  0,;
  Caption    = "需要準備",;
  ForeColor   = RGB(255,255,255),;
  FontName   = "細明體",;
  FontSize   = 12,;
  Left     = 15,;
  Top      = 52

ADD OBJECT txtTotal AS TEXTBOX WITH;
  Enabled    = .F.,;
  FontName   = "細明體",;
  FontSize   = 11,;
  Height    = 23,;
  Left     = 100,;
  Top      = 50,;
  Width     = 60

 ADD OBJECT (SYS(2015)) AS LABEL WITH;
  AutoSize   = .T.,;
  BackStyle   =  0,;
  Caption    = "種車票",;
  ForeColor   = RGB(255,255,255),;
  FontName   = "細明體",;
  FontSize   = 12,;
  Left     = 165,;
  Top      = 52

 ADD OBJECT lblRecL AS LABEL WITH;
  AutoSize   = .T.,;
  BackStyle   =  0,;
  Caption    = "計算中...",;
  ForeColor   = RGB(255,255,0),;
  FontName   = "細明體",;
  FontSize   = 10,;
  Visible    = .F.,;
  Left     = 15,;
  Top      = 75

 ADD OBJECT lblRec AS LABEL WITH;
  AutoSize   = .T.,;
  BackStyle   =  0,;
  Caption    = "",;
  ForeColor   = RGB(255,255,0),;
  FontName   = "細明體",;
  FontSize   = 10,;
  Visible    = .F.,;
  Left     = 15,;
  Top      = 95

 ADD OBJECT cmdYes AS CommandButton WITH;
  Caption    = "執行",;
  Height    = 25,;
  Width     = 75,;
  Left     = 15,;
  Top      = ThisForm.Height-36

 ADD OBJECT cmdCancel AS CommandButton WITH;
  Caption    = "離開",;
  Height    = 25,;
  Width     = 75,;
  Left     = ThisForm.Width-90,;
  Top      = ThisForm.Height-36

 PROCEDURE cmdYes.Click
 * One
 WITH This.Parent
  STORE .spinNum.Value TO UserForm1_nNum
 ENDWITH
 UserForm1_nCircle = 2
 * Two
 * > 計算共有幾組以供顯示資訊使用
 M_nReccount = 1
 FOR UserForm1_SUB_A = UserForm1_nNum-UserForm1_nCircle+1 TO UserForm1_nNum
  M_nReccount = M_nReccount * UserForm1_SUB_A
 ENDFOR
 FOR UserForm1_SUB_A = 1 TO UserForm1_nCircle
  M_nReccount = M_nReccount / UserForm1_SUB_A
 ENDFOR
 * > 顯示記錄產生筆數資訊
 WITH This.Parent
  .lblRecL.Caption = "計算中...  " + TRANSFORM(M_nReccount,M_nTran)
  .lblRec.Caption = ""
  .lblRecL.Visible = .T.
  .lblRec.Visible = .T.
 ENDWITH
 __Esc  = .F.
 __IsCalc = .T.
 UserForm1_nTotal = TT(UserForm1_nNum,UserForm1_nCircle)
 __IsCalc = .F.
 WITH This.Parent
  .lblRec.Caption = PADR(.lblRec.Caption,LEN(M_nTran))
 ENDWITH
 WITH This.Parent
  .txtTotal.Value = TRANSFORM(UserForm1_nTotal,"@R 99,999")
 ENDWITH
 WITH This.Parent
  .lblRecL.Visible = .F.
  .lblRec.Visible = .F.
 ENDWITH
 WAIT CLEAR
 ENDPROC

 PROCEDURE KeyPress
 LPARAMETERS nKeyCode, nShiftAltCtrl
 DO CASE
 * >> ESC
 CASE nKeyCode = 27
    __Esc = .T.
    IF !__IsCalc
     .cmdCancel.SetFocus
     .cmdCancel.Click
    ENDIF
 ENDCASE
 ENDPROC

 PROCEDURE Destroy
 ThisForm.Visible = .F.
 RELEASE THISFORM
 ENDPROC

 PROCEDURE cmdCancel.Click
 THISFORM.Destroy()
 ENDPROC
ENDDEFINE
* ---------- ENDDEFINE CLASS ---------- *


FUNCTION TT
* ------------------------ *
* Input:
*  L_nNum  N 要幾個數字
*  L_nCircle N 一次抽幾個
* Output:
*  Lo_nTotal N 共有幾組
* ------------------------ *
PARAMETERS L_nNum,L_nCircle
LOCAL W1_SUB_A,W1_SUB_B
M_nMaxNum  = L_nNum
M_nFiledCNT = L_nCircle
* 最後一筆的合計數:避免最後一筆會重覆一次
M_nSumOfLast = 0
FOR W1_SUB_A = M_nMaxNum-M_nFiledCNT+1 TO M_nMaxNum
 M_nSumOfLast = M_nSumOfLast + W1_SUB_A
ENDFOR
* 建立暫存表格檔
W1_cCursorString = "CREATE CURSOR TMP_TT ("
FOR W1_SUB_A = 1 TO M_nFiledCNT
 W1_cSUB_A = TRANSFORM(W1_SUB_A,"@L 999")
 IF !W1_SUB_A = 1
  W1_cCursorString = W1_cCursorString + ","
 ENDIF
 W1_cCursorString = W1_cCursorString + "N" + W1_cSUB_A + " N(3)"
ENDFOR
W1_cCursorString = W1_cCursorString + ")"
SELECT 0
&W1_cCursorString
* 取得排列組合的資料
=CIRCLE(1,L_nCircle,1)
* 顯示需要準備幾種車票(只有一半)
Lo_nTotal = RECCOUNT("TMP_TT")
* 關閉暫存表格檔
USE IN TMP_TT
RETURN Lo_nTotal * 2

FUNCTION CIRCLE
* 遞回函數
* ------------------------------------ *
* L_nMinNum N 最小數
* L_nChoice N 同一次還剩幾個數可以抽
* L_nWho  N 每一次抽的第幾個數
* ------------------------------------ *
PARAMETERS L_nMinNum,L_nChoice,L_nWho
LOCAL W1_nMinNum,W1_nChoice,W1_nWho
LOCAL W1_SUB_A,W1_SUB_B,W1_nSumOfLast
LOCAL W1_nNextMinNum,W1_nNextChoice,W1_nNextWho
W1_nMinNum = L_nMinNum
W1_nChoice = L_nChoice
W1_nWho  = L_nWho
* >
IF __Esc
 RETURN
ENDIF
IF W1_nChoice = 0
 RETURN
ENDIF
IF W1_nWho > M_nFiledCNT
 RETURN
ENDIF
* >
IF W1_nWho = 1
 SELECT TMP_TT
 APPEND BLANK
 WW_oMESSAGEBOX.lblRec.Caption = TRANSFORM(RECNO(),M_nTran) + ;
                 " (按 Esc 鍵中斷)"
ENDIF
* >
FOR W1_SUB_A = W1_nMinNum TO M_nMaxNum-W1_nChoice+1
 REPLACE ("N"+TRANSFORM(W1_nWho,"@L 999")) WITH W1_SUB_A
 * > 當每一筆的資料填滿時要新增下一筆
 IF W1_nWho = M_nFiledCNT
  * >> Set Filter:不是最後一筆
  W1_nSumOfLast = 0
  FOR W1_SUB_B = 1 TO M_nFiledCNT
   W1_nSumOfLast = W1_nSumOfLast + EVAL("N"+TRANSFORM(W1_SUB_B,"@L 999"))
  ENDFOR
  IF W1_nSumOfLast = M_nSumOfLast
   LOOP
  ENDIF
  * >> 新增
  SELECT TMP_TT
  SCATTER TO W1_aTT
  APPEND BLANK
  WW_oMESSAGEBOX.lblRec.Caption = TRANSFORM(RECNO(),M_nTran) + ;
                  " (按 Esc 鍵中斷)"
  * >
  IF RECNO() > 1 AND W1_nWho > 1
   GATHER FROM W1_aTT
  ENDIF
 ENDIF
 * >
 IF !__Esc
  __Esc = INKEY() = 27
 ENDIF
 IF __Esc
  RETURN
 ENDIF
 W1_nNextMinNum = W1_SUB_A  + 1
 W1_nNextChoice = W1_nChoice - 1
 W1_nNextWho  = W1_nWho  + 1
 =CIRCLE(W1_nNextMinNum,W1_nNextChoice,W1_nNextWho)
 IF __Esc
  RETURN
 ENDIF
ENDFOR
RETURN
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件 MSN Messenger
從之前的文章開始顯示:   
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區 所有的時間均為 台北時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
無法 在這個版面附加檔案
無法 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作