想按自己的思路重写一些经典算法,以提高编程水平,请高手多执教。

问题:
一个小孩买了价值少于1美元的糖,并将1美元的钱交给售货员。售货员希望用数目最少的硬币找给小孩。假设提供了数目不限的面值为2 5美分、1 0美分、5美分、及1美分的硬币。售货员分步骤组成要找的零钱数,每次加入一个硬币。选择硬币时所采用的贪婪准则如下:每一次选择应使零钱数尽量增大。为保证解法的可行性(即:所给的零钱等于要找的零钱数),所选择的硬币不应使零钱总数超过最终所需的数目。

假设需要找给小孩6 7美分,首先入选的是两枚2 5美分的硬币,第三枚入选的不能是2 5美分的硬币,否则硬币的选择将不可行(零钱总数超过6 7美分),第三枚应选择1 0美分的硬币,然后是5美分的,最后加入两个1美分的硬币。

贪婪算法有种直觉的倾向,在找零钱时,直觉告诉我们应使找出的硬币数目最少(至少是接近最少的数目)。可以证明采用上述贪婪算法找零钱时所用的硬币数目的确最少(见练习1)。


找硬币算法(贪婪/回溯算法).<!--找钱(硬币)问题,要求找回的硬币最少-->
找硬币算法(贪婪/回溯算法).
<%
找硬币算法(贪婪/回溯算法).
Dim sAction
找硬币算法(贪婪/回溯算法).
Dim sResultString '表单提交后结果信息
找硬币算法(贪婪/回溯算法).
sAction = LCase(Trim(Request("action")))
找硬币算法(贪婪/回溯算法).
If sAction = "do" Then
找硬币算法(贪婪/回溯算法).    
'获取值
找硬币算法(贪婪/回溯算法).
    Dim nMoney, nKeepMoney, sCoin
找硬币算法(贪婪/回溯算法).    nMoney 
= Trim(Request.Form("Money"))
找硬币算法(贪婪/回溯算法).    sCoin 
= Trim(Request.Form("Coin"))
找硬币算法(贪婪/回溯算法).    
'response.write nMoney & "<br/>"
找硬币算法(贪婪/回溯算法).
    'response.write sCoin & "<br/>"
找硬币算法(贪婪/回溯算法).
    nKeepMoney = nMoney
找硬币算法(贪婪/回溯算法).    
'错误处理
找硬币算法(贪婪/回溯算法).
    If IsNumeric(nMoney) = True Then
找硬币算法(贪婪/回溯算法).        nMoney 
= CLng(nMoney)
找硬币算法(贪婪/回溯算法).    
Else
找硬币算法(贪婪/回溯算法).        OutputError 
"[钱]必须是数字!"
找硬币算法(贪婪/回溯算法).    
End If
找硬币算法(贪婪/回溯算法).    
If sCoin = "" Then OutputError "[币值]不能为空!"
找硬币算法(贪婪/回溯算法).    
找硬币算法(贪婪/回溯算法).    
Dim bFindSolution, aSolution() '是否找到找钱方案(boolean), 方案结果(二维数组)
找硬币算法(贪婪/回溯算法).
    Dim aCoin, nCoinClass, nPayCoinCount '硬币币值(一维数组), 币值种类个数, 找出的硬币数量
找硬币算法(贪婪/回溯算法).
    Dim i, t, sum '循环变量, 交换变量,累加变量
找硬币算法(贪婪/回溯算法).
    bFindSolution = False
找硬币算法(贪婪/回溯算法).    nPayCoinCount 
= 0
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).    aCoin 
= Split(sCoin, ",")
找硬币算法(贪婪/回溯算法).    nCoinClass 
= UBound(aCoin, 1'隔开逗号得到硬币种类个数
找硬币算法(贪婪/回溯算法).
    ReDim aSolution(nCoinClass, 1'定义结果为二维数组, aSolution(x,0)表示币值, aSolution(x,1)表示该币值找回的个数
找硬币算法(贪婪/回溯算法).
    aCoin = QuickSort(aCoin) '将币值数组升序排序
找硬币算法(贪婪/回溯算法).
    For i = 0 To nCoinClass
找硬币算法(贪婪/回溯算法).        
If IsNumeric(aCoin(i)) = False Then OutputError "币值只能是数字,[" & aCoin(i) & "]不是数字!"
找硬币算法(贪婪/回溯算法).        
If aCoin(i) = 0 Then OutputError "币值不能为零!"
找硬币算法(贪婪/回溯算法).        aSolution(i,
0= aCoin(i)
找硬币算法(贪婪/回溯算法).        aSolution(i,
1= 0
找硬币算法(贪婪/回溯算法).    
Next
找硬币算法(贪婪/回溯算法).    
找硬币算法(贪婪/回溯算法).    
'===============================
找硬币算法(贪婪/回溯算法).
    '找出找回硬币最少的方案
找硬币算法(贪婪/回溯算法).
    '===============================
找硬币算法(贪婪/回溯算法).
    
找硬币算法(贪婪/回溯算法).    
'每次找回的硬币记录,存在数组中
找硬币算法(贪婪/回溯算法).
    Dim aRecord(), nRecordCount, nRecordIndex '记录数组(一维,存放币值), 数组长度(即最多找回的硬币个数或找的次数), 当前操作的数组下标
找硬币算法(贪婪/回溯算法).
    nRecordCount = nMoney / aCoin(0'钱/最小币值, 取得最多找回的个数
找硬币算法(贪婪/回溯算法).
    ReDim aRecord(nRecordCount)
找硬币算法(贪婪/回溯算法).    nRecordIndex 
= 0
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).    i 
= nCoinClass '取最大币值下标
找硬币算法(贪婪/回溯算法).
    Do While True    
找硬币算法(贪婪/回溯算法).        sum 
= 0
找硬币算法(贪婪/回溯算法).        
Do While i>=0 And nMoney-aCoin(i)>=0 '剩余的钱比当前的币值小
找硬币算法(贪婪/回溯算法).
            nMoney = nMoney - aCoin(i) '扣掉拿出的币值
找硬币算法(贪婪/回溯算法).
            Call InCrease(aCoin(i)) '结果中该币值的个数加1
找硬币算法(贪婪/回溯算法).
            nPayCoinCount = nPayCoinCount + 1 '总的拿出的硬币个数加1
找硬币算法(贪婪/回溯算法).
            If i > 0 Then
找硬币算法(贪婪/回溯算法).                aRecord(nRecordIndex) 
= aCoin(i) '记录
找硬币算法(贪婪/回溯算法).
                nRecordIndex = nRecordIndex + 1
找硬币算法(贪婪/回溯算法).                t 
= i '保留当前币值的下标, 以便下次循环从 这个下标-1 开始
找硬币算法(贪婪/回溯算法).
            Else
找硬币算法(贪婪/回溯算法).                sum 
= sum + aCoin(i) '最小币值的钱累加
找硬币算法(贪婪/回溯算法).
            End If
找硬币算法(贪婪/回溯算法).        
Loop
找硬币算法(贪婪/回溯算法).        
If nMoney = 0 Then
找硬币算法(贪婪/回溯算法).            bFindSolution 
= True
找硬币算法(贪婪/回溯算法).            
Exit Do
找硬币算法(贪婪/回溯算法).        
End If
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).        
If i > 0 Then
找硬币算法(贪婪/回溯算法).            i 
= i - 1 '当前币值太大, 进行下次更小 币值的循环
找硬币算法(贪婪/回溯算法).
        Else
找硬币算法(贪婪/回溯算法).            
If CLng(aRecord(0)) = 0 Then '如果记录中不含任何币值, 表示全部回溯都已经试过仍没有方案
找硬币算法(贪婪/回溯算法).
                bFindSolution = False
找硬币算法(贪婪/回溯算法).                
Exit Do
找硬币算法(贪婪/回溯算法).            
End If
找硬币算法(贪婪/回溯算法).            
'以下做 回溯操作
找硬币算法(贪婪/回溯算法).
            nMoney = nMoney + sum
找硬币算法(贪婪/回溯算法).            nMoney 
= nMoney + aRecord(nRecordIndex-1)
找硬币算法(贪婪/回溯算法).            nPayCoinCount 
= nPayCoinCount - 1
找硬币算法(贪婪/回溯算法).            
Call DeCrease(aRecord(nRecordIndex-1))
找硬币算法(贪婪/回溯算法).            aRecord(nRecordIndex
-1= 0
找硬币算法(贪婪/回溯算法).        
End If
找硬币算法(贪婪/回溯算法).    
Loop
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).    
'输出方案
找硬币算法(贪婪/回溯算法).
    If bFindSolution = True Then
找硬币算法(贪婪/回溯算法).        sResultString 
= "<b>条件:</b>" & "<br/>" & _
找硬币算法(贪婪/回溯算法).                        
"钱:" & nKeepMoney & "<br/>" & _
找硬币算法(贪婪/回溯算法).                        
"币值:" & sCoin & "<br/><br/>" & _
找硬币算法(贪婪/回溯算法).                        
"<b>找回硬币最少的方案:</b>" & "<br/>" & _
找硬币算法(贪婪/回溯算法).                        
"最少找回个数:" & nPayCoinCount & "<br/>"
找硬币算法(贪婪/回溯算法).        
For i = 0 To nCoinClass
找硬币算法(贪婪/回溯算法).            sResultString 
= sResultString & "&nbsp;&nbsp;&nbsp;&nbsp;" & "币值:" & aSolution(i,0& "&nbsp;&nbsp;" & "个数:" & aSolution(i,1& "<br/>"
找硬币算法(贪婪/回溯算法).        
Next
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).    
Else
找硬币算法(贪婪/回溯算法).        sResultString 
= "<b><font color='red'>不能用指定的币值找回硬币!</font></b>"
找硬币算法(贪婪/回溯算法).    
End If
找硬币算法(贪婪/回溯算法).    
找硬币算法(贪婪/回溯算法).
End If
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).
'指定币值找回个数加1
找硬币算法(贪婪/回溯算法).
Sub InCrease(n_Coin)
找硬币算法(贪婪/回溯算法).    
Dim i
找硬币算法(贪婪/回溯算法).    
For i = 0 To nCoinClass
找硬币算法(贪婪/回溯算法).        
If CLng(aSolution(i,0)) = CLng(n_Coin) Then
找硬币算法(贪婪/回溯算法).            aSolution(i,
1= aSolution(i,1+ 1
找硬币算法(贪婪/回溯算法).            
Exit Sub
找硬币算法(贪婪/回溯算法).        
End If
找硬币算法(贪婪/回溯算法).    
Next
找硬币算法(贪婪/回溯算法).
End Sub
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).
'指定币值找回个数加1
找硬币算法(贪婪/回溯算法).
Sub DeCrease(n_Coin)
找硬币算法(贪婪/回溯算法).    
Dim i
找硬币算法(贪婪/回溯算法).    
For i = 0 To nCoinClass
找硬币算法(贪婪/回溯算法).        
If CLng(aSolution(i,0)) = CLng(n_Coin) Then
找硬币算法(贪婪/回溯算法).            aSolution(i,
1= aSolution(i,1- 1
找硬币算法(贪婪/回溯算法).            
Exit Sub
找硬币算法(贪婪/回溯算法).        
End If
找硬币算法(贪婪/回溯算法).    
Next
找硬币算法(贪婪/回溯算法).
End Sub
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).
'快速排序
找硬币算法(贪婪/回溯算法).
Function QuickSort(a_Data)
找硬币算法(贪婪/回溯算法).    
Dim i, j
找硬币算法(贪婪/回溯算法).    
Dim count, t
找硬币算法(贪婪/回溯算法).    count 
= UBound(a_Data, 1)
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).    
For i = 0 To count-1
找硬币算法(贪婪/回溯算法).        
For j = i+1 To count
找硬币算法(贪婪/回溯算法).            
If CLng(a_Data(i)) > CLng(a_Data(j)) Then
找硬币算法(贪婪/回溯算法).                t 
= a_Data(i)
找硬币算法(贪婪/回溯算法).                a_Data(i) 
= a_Data(j)
找硬币算法(贪婪/回溯算法).                a_Data(j) 
= t
找硬币算法(贪婪/回溯算法).            
End If
找硬币算法(贪婪/回溯算法).        
Next
找硬币算法(贪婪/回溯算法).    
Next
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).    QuickSort 
= a_Data
找硬币算法(贪婪/回溯算法).
End Function
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).
'输出错误提示
找硬币算法(贪婪/回溯算法).
Sub OutputError(str)
找硬币算法(贪婪/回溯算法).    Response.Write 
"<script language='javascript'>alert('" & str & "');history.back();</script>"
找硬币算法(贪婪/回溯算法).    Response.End
找硬币算法(贪婪/回溯算法).
End Sub
找硬币算法(贪婪/回溯算法).%
>
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).
<html>
找硬币算法(贪婪/回溯算法).
<head>
找硬币算法(贪婪/回溯算法).
<title>找钱(硬币)问题,要求找回的硬币最少</title>
找硬币算法(贪婪/回溯算法).
</head>
找硬币算法(贪婪/回溯算法).
<body>
找硬币算法(贪婪/回溯算法).
<p><%=sResultString%></p>
找硬币算法(贪婪/回溯算法).
<p align='center'>
找硬币算法(贪婪/回溯算法).

找硬币算法(贪婪/回溯算法).
<table border=0>
找硬币算法(贪婪/回溯算法).
<form name="form1" method="post" action="?action=do">
找硬币算法(贪婪/回溯算法).    
<tr><td>钱:</td><td><input type="text" name="Money" value="" size="10"></td></tr>
找硬币算法(贪婪/回溯算法).    
<tr><td>币值:</td><td><input type="text" name="Coin" value="" size="30">&nbsp;<font color='gray'>多个以逗号隔开</font></td></tr>
找硬币算法(贪婪/回溯算法).
    <tr><td colspan="2"><input type="submit" name="submit" value="找钱方案"></td></tr>
找硬币算法(贪婪/回溯算法).
</form>
找硬币算法(贪婪/回溯算法).
</table>
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).
</p>
找硬币算法(贪婪/回溯算法).
</body>
找硬币算法(贪婪/回溯算法).
</html>
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).
找硬币算法(贪婪/回溯算法).

相关文章: