日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基础DP(初级版)

發布時間:2023/11/29 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基础DP(初级版) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  本文主要內容為基礎DP,內容來源為《算法導論》,總結不易,轉載請注明出處。

  后續會更新出kuanbin關于基礎DP的題目......

動態規劃:

  動態規劃用于子問題重疊的情況,即不同的子問題具有相同的公共子子問題,在這種情況下分治算法會做許多不必要的工作,它會反復求解那些子子問題使得程序邊的緩慢。而動態規劃則對每個問題?只求解一次,將其解保存在一個表格中,從而避免一些不必要的重復計算。

  動態規劃常用來求解最優化問題,這類問題可以有很多解,每個解都有一個值,我們希望尋找具有最優值的解,我們稱這樣的解為問題的一個最優解,而不是最優解,因為可能有多個最優解。

  動態規劃設計算法的一般步驟:

  ?  1.刻畫一個最優解的結構特征。

    2.遞歸的定義最優解的值。

    3.計算最優解的值,通常采用自地向上的方法。

    4.利用計算出的信息構造一個最優解。

  動態規劃的兩種基本解題步驟:

    第一種為自頂向下法:此方法仍按自然的遞歸形式編寫過程,但過程中會保存每個子問題的解。當需要一個子問題的解時,過程中會首先檢查是否此問題已經被求解,如果是則直接返回該解,否則按通常的方式計算,我們稱這個遞歸過程時帶備忘的,因為他記住了之前的計算結果,不會進行重復的計算。

?

    第二種為自底向上法:這種方法一般需要恰當定義子問題的規模的概念,使得任何子問題都只依賴更小的子問題求解。因而我們可以將子問題的規模排序按由小到大的順序進行求解。當求解某個子問題時,它所依賴的更小的子問題已經得到解決,結果已經保存。每個子問題也只需求解一次。

  最優子結構:

    問題的最優解由相關子問題的最優解構成,這些子問題可以獨立求解。

  重構解

    在求解過程中保存相應的狀態到另一個輔助數組中即可。

例:鋼條切割問題:一根長度為n的鋼條,切割不同的長度?i?對應不同的價格p[ i ],?問你如何切割一根鋼條使得利益最大化。

  n = i1 + i2 + ... + ik;

  遞推式:

    rn = max(pn, r1 + r(n-1), r2 + r(n-2)...r(n-1) +r1)。

  

1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 1000, INF = -0x3f3f3f3f; 7 long long dp[maxn], s[maxn]; 8 long long p[maxn] = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30}; 9 long long q; 10 11 long long memoized_cut_rod(int n) { 12 if(dp[n] >= 0) return dp[n]; 13 if(n == 0) q = 0; 14 else q = INF; 15 for(int i = 1; i <= n; i ++) 16 q = max(q, p[i] + memoized_cut_rod(n - i)); 17 dp[n] = q; 18 return q; 19 } 20 21 long long bottom_up_cut_rod(int n) { 22 dp[0] = 0; 23 for(int j = 1; j <= n; j ++) { 24 q = INF; 25 for(int i = 1; i <= j; i ++) { 26 q = max(q, p[i] + dp[j - i]); 27 } 28 dp[j] = q; 29 } 30 return dp[n]; 31 } 32 33 int main () { 34 long long n; 35 memset(dp, -1, sizeof dp); 36 while(cin >> n) { 37 long long ans = memoized_cut_rod(n); 38 printf("%d\n", ans); 39 ans = bottom_up_cut_rod(n); 40 printf("%d\n", ans); 41 } 42 }

?

  重構解:

long long bottom_up_cut_rod(int n) {dp[0] = 0;for(int j = 1; j <= n; j ++) {q = INF;for(int i = 1; i <= j; i ++) {if(p[i] + dp[j - i] > q) {q = max(q, p[i] + dp[j - i]);s[j] = i;}}dp[j] = q;}return dp[n]; }while(n) {cout << s[n] << '\t';n = n - s[n]; }

?

?例二:求斐波納挈數

  

#include <iostream> using namespace std;const int maxn = 1000, INF = 0x3f3f3f3f; long long dp[maxn];long long calculate_fib(int n) {if(n == 0 && n == 1) return 1;for(int i = 2; i <= n; i ++)if(dp[i] < 0) dp[i] = dp[i - 1] + dp[i - 2];return dp[n]; }int main () {long long n;for(int i = 0; i < maxn; i ++) dp[i] = -INF;dp[0] = dp[1] = 1;while(cin >> n) {cout << calculate_fib(n);} }

?

轉載于:https://www.cnblogs.com/bianjunting/p/10551303.html

總結

以上是生活随笔為你收集整理的基础DP(初级版)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。