2023-04-28

【學習筆記】動態規劃(2) -- 以 ZeroJudge d637. 路過的鴨duck 為例

開場

上一篇文章中,我們利用了這個網站來輔助我們了解與完成1-0背包問題,今天我們要以d637. 路過的鴨duck為例,帶來程式碼的部分!

動態規劃

上一篇文章,我們似乎還沒好好地介紹什麼是「動態規劃」,「動態規劃」,英文為Dynamic programming,簡稱DP,是一種重要的演算法(algorithm),在利用「動態規劃」解題時,若問題可以切割成許多相對較簡單的小問題,那麼經由將小問題解決可以組合成大問題(原問題)的解
接下來,我們1-0背包問題的觀念為基礎,d637. 路過的鴨duck為例,帶出程式碼!

範例程式


#include <bits/stdc++.h>
using namespace std;
int w[10001],v[10001],dp[10001][10001];
int n;
int main(){
    while(cin>>n){
        for(int i=0;i<n;i++){
            cin>>w[i]>>v[i];
        }
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++){
            for(int j=0;j<=100;j++){
                if(0>j-w[i])
                   dp[i+1][j]=dp[i][j];
                else
                   dp[i+1][j]=max(dp[i][j], dp[i][j-w[i]]+v[i]);
            }
        }
        cout<<dp[n][100];
    }
    return 0;
}

解析

所以,一開始我們先定義
int w[10001],v[10001],dp[10001][10001];
int n;
這幾個變數,分別用來儲存物品重量物品價值與我們的表格(也就是在第一篇時的那些表格),另外定義一個變數n,這樣子可以做到多行輸入
接下來可以看見下面這段:
memset(dp,0,sizeof(dp));
這一段的意思是:我把我的dp陣列的值全部設定為0,sizeof(dp)則是指設定的數量!
for(int i=0;i<n;i++){
    for(int j=0;j<=100;j++){
	if(0>j-w[i])
    	    dp[i+1][j]=dp[i][j];
	else
    	    dp[i+1][j]=max(dp[i][j], dp[i][j-w[i]]+v[i]);
    	}
}
上面這段則是在執行動態規劃的過程,我們來一步一步地做講解:
在第11、12行有兩個for迴圈,而這2個迴圈是用於遍歷我們的陣列,這麼做是為了確認陣列內是否存在其他最優解。在迴圈裡面我們塞入了一個判斷式,而這個判斷式式什麼意思呢?
if(0>j-w[i])-else是在判斷當前背包負重能力是否小於物品重,若是,則將dp[i+1][j]移下來,若否,則在dp[i][j]dp[i][j-w[i]]+v[i]之間取其大,為最優解。
最後再cout最終解即是解答囉!

結語

演算法需要多花時間理解與練習,還望各位多花時間在練習上!希望這篇文章對您有幫助 :D

沒有留言:

張貼留言

留言注意事項:

勾選「通知我」可在後續有回覆時寄信給您!

使用Safari恐無法登入留言(只能以匿名方式留言)!

敬請詳細描述問題,以方便站方迅速判斷與解答!

依據本站免責聲明,本站得逕行刪除含有不適合存在於本站的言論與字詞的發言,敬請謹慎留言!