1. 程式人生 > 其它 >學號-姓名 實驗二 個人專案—《D{0-1}揹包問題》專案報告

學號-姓名 實驗二 個人專案—《D{0-1}揹包問題》專案報告

專案 內容
課程班級部落格連結 https://edu.cnblogs.com/campus/xbsf/2019nwnucs
這個作業要求連結 https://edu.cnblogs.com/campus/xbsf/2019nwnucs/homework/12527
我的課程學習目標 1. 掌握軟體專案個人開發流程。
2. 掌握Github釋出軟體專案的操作方法。
這個作業在哪些方面幫助我實現學習目標 1. 熟悉了軟體專案原始碼常用整合開發軟體工具。
2.瞭解了Github釋出軟體專案的操作方法
3.瞭解個各種程式碼管理軟體的特點與區別。
專案Github的倉庫連結地址 https://github.com/201971010245/245D0-1

實驗內容
任務1:閱讀教師部落格“常用原始碼管理工具與開發工具
完成任務1後,對三位同學進行了點評實驗點評如下:

專案 內容
樑春雲同學作業評價連結 https://www.cnblogs.com/liangchunyun/p/15969570.html
謝雨涵同學作業評價連結 https://www.cnblogs.com/201971010247xyh/p/15966838.html
孫得弘同學作業評價連結 https://www.cnblogs.com/sundh1017/p/15954270.html

任務2:總結詳細閱讀《構建之法》第1章、第2章,掌握PSP流程
閱讀《構建之法》第1章,第2章,第3章總結連結如下:

  • 第一章
  1. 軟體構建的過程
    構建不僅僅是cc和link命令,以後複雜的軟體不但要有合理的軟體構架、軟體設計與實現,還要有各種檔案和資料來描述各個程式檔案之間的依賴關係、編譯引數、連結引數,等等。
    2.軟體=程式+軟體工程
    3.軟體企業=軟體+商業模式
    4.軟體的特殊性
  • 複雜性
  • 不可見性
  • 易變性
  • 服從性
  • 非連續性
  • PSP流程如下:
p 預估時間 (min) 實際完成時間(min)
計劃 8 9
開發 85 90
需求分析 8 10
生成設計文件 2 5
設計複審 4 5
程式碼規劃 2 2
具體設計 5 5
具體編碼 30 35
程式碼複審 10 8
測試 4 3
測試報告 5 5
計算工作量 5 5
事後總結,並提出過程改進計劃 10 10

任務3:專案開發

  • 任務描述如下:
    揹包問題(Knapsack Problem,KP)是NP Complete問題,也是一個經典的組合優化問題,有著廣泛而重要的應用背景。{0-1}揹包問題({0-1 }Knapsack Problem,{0-1}KP)是最基本的KP問題形式,它的一般描述為:從若干具有價值係數與重量係數的物品(或項)中,選擇若干個裝入一個具有載重限制的揹包,如何選擇才能使裝入物品的重量係數之和在不超過揹包載重前提下價值係數之和達到最大?
    {0-1}KP資料集是研究{0-1}揹包問題時,用於評測和觀察設計演算法效能的標準資料集;動態規劃演算法、回溯演算法是求解{0-1}揹包問題的經典演算法。查閱相關資料,設計一個採用貪心演算法、動態規劃演算法、回溯演算法求解{0-1}揹包問題的程式
  • 需求分析
  1. 資料集檔案進行資料讀取;
  2. 對某一組資料進行視覺化,以散點圖的方式呈現給使用者;
  3. 將資料按照一定順序進行排序;
  4. 通過回溯演算法和動態規劃演算法進行程式實現,將結果存入檔案
  • 功能設計
    1.可正確讀入實驗資料檔案的有效{0-1}KP資料;
    2.能夠繪製任意一組{0-1}KP資料以重量為橫軸、價值為縱軸的資料散點圖;
    3.能夠對一組{0-1}KP資料按重量比進行非遞增排序;
    4.使用者能夠自主選擇貪心演算法、動態規劃演算法、回溯演算法求解指定{0-1} KP資料的最優解和求解時間(以秒為單位);
    5.任意一組{0-1} KP資料的最優解、求解時間和解向量可儲存為txt檔案或匯出EXCEL檔案。
  • 任務分析:
    01揹包屬於找最優解問題,用回溯法需要構造解的子集樹。對於每一個物品i,對於該物品只有選與不選2個決策,總共有n個物品,可以順序依次考慮每個物品,這樣就形成了一棵解空間樹: 基本思想就是遍歷這棵樹,以列舉所有情況,最後進行判斷,如果重量不超過揹包容量,且價值最大的話,該方案就是最後的答案。
    在搜尋狀態空間樹時,只要左子節點是可一個可行結點,搜尋就進入其左子樹。對於右子樹時,先計算上界函式,以判斷是否將其減去(剪枝)。
  • 設計實現
  1. 利用動態規劃演算法和回溯演算法來實現{0-1}揹包問題,可以用一個二維陣列來記錄揹包的狀態。假設用value[N][V]來儲存中間狀態值,value[i][j]表示前i件物品能裝入容量為j的揹包中的物品價值總和的最大值,則我們最終只需求知value[i=N][j=V]的值。
    1) 若w[i]>j,則第i件物品肯定不能裝入容量為j的揹包,此時value[i][j]=value[i-1][j]
  1. 若w[i]<=j,則首先明確的是這件物品是可以裝入容量為j的揹包的,那麼如果我們將該物品裝入,則有
    value[i][j]=value[i-1][j-w[i]]+v[i]
    2.流程圖
  • 測試執行

  • 程式碼片段

  1. 散點圖
點選檢視程式碼
x = np.linspace(0.05, 10, 1000)  

np.random.seed(22)
y = np.random.randn(1000)

# 圖表元素中正常顯示中文字元
plt.rcParams['font.sans-serif'] = 'SimHei'
# 座標軸刻度標籤正常顯示負號
plt.rcParams['axes.unicode_minus'] = False

plt.scatter(x, y,
            s=87,  # 標記點大小
            marker='*',  # 標記點的樣式 星號
            c='g',  # green 綠色
            linewidths=0.41,
            edgecolor='y',  # 邊緣顏色
            label='scatter figure')

plt.xticks(size=12, color='grey')  # x 軸刻度標籤
plt.yticks(size=12, color='grey')  # y 軸刻度標籤
plt.title('散點圖', size=14, color='y');  # 新增圖表標題
plt.legend()  # 新增圖例

# 設定座標軸刻度範圍
plt.xlim(-0.5, 10.5)  
plt.ylim(-3.5, 3.5);

2.主程式程式碼塊

點選檢視程式碼
if __name__ == '__main__':
    fileName = getData()
    # 列表中包含若干個子列表,每個子列表包含一組資料的價值資訊,每個子列表又包含若干個三元組列表,三元組列表記錄了記錄了該組資料每個項集
    print('資料讀入完成!')
    print('價值資訊:')
    for i in profit[0]:
        print(i)
    # 同價值資訊,用於記錄重量資訊
    print('重量資訊:')
    print(weight)
    # 列表包含若干子列表,一個子列表表示一組資料的價值-重量-價值重量比資訊,子列表分為若干九元組。九元組記錄了改組資料的價值-重量-價值重量比九條資訊
    print('價值-重量-價值重量比資訊:')
    print(prowei)
    while (True):
        x = int(input('請選擇:\n1、畫散點圖\n2、非遞增排序\n3、求解\n'))
        if x == 1:
            n = int(input('請選擇對第幾條資料做散點圖'))
            show(n - 1)
            continue
        elif x == 2:
            n = int(input('請選擇要對第幾條資料進行排序'))
            sort(n - 1)
            continue
        elif x == 3:
            n = int(input('請選擇演算法\n1、回溯法\n2、動態規劃演算法\n'))
            num = int(input('請輸入要求解第幾組資料'))
            maxWeight = int(input('請輸入揹包容納的最大重量'))
            if n == 1:
                profit[num - 1] = [[0, 0, 0]] + profit[num - 1]
                weight[num - 1] = [[0, 0, 0]] + weight[num - 1]
                for i in profit[0]:
                    print(i)
                time1 = time.time()
                huisu(num - 1, maxWeight, 0, 0, 0, 0)
                time2 = time.time()
                endMax.sort(reverse=True)
                print('最大價值:' + str(endMax[0]))
                print('執行時間:' + str(time2 - time1) + 's')
                for item in range(len(pathList)):
                    if pathList[item] == endMax[0]:
                        path(item, num - 1)
            elif n == 2:
                time1 = time.time()
                dp(num - 1, maxWeight)
                time2 = time.time()
                print(time2 - time1)
            x = int(input('請選擇:\n1.儲存為txt\n2.不儲存'))
            if x == 1:
                saveTxt(fileName, num, maxWeight, endMax[0], time2 - time1)
            else:
                pass
        else:
            print('輸入有誤,請重新輸入!')
            continue
  • 專案總結
    此次實驗主要是關於揹包問題的動態規劃法、回溯法求解揹包問題,在程式設計過程中,按程式功能進行分塊,通過模組化的設計,讓我更加理解了軟體功能需求,同時也提高了我程式完成的效率。