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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

数据结构与算法(C++)– 动态规划(Dynamic Programming)

發布時間:2025/3/12 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构与算法(C++)– 动态规划(Dynamic Programming) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

動態規劃(Dynamic Programming)


理解動態規劃的好文:https://www.sohu.com/a/153858619_466939


1、基礎

**定義:**遞歸算法經常會有一些重復的計算,導致程序效率低。動態規劃就是解決這個問題的方法。

動態規劃的組成部分:

  • 最優子結構:分解問題
  • 邊界:遞歸的終止條件
  • 狀態轉移方程:遞歸的方程

動態規劃的解題步驟:

  • 分解問題,得到狀態轉移方程
  • 暴力搜索,找到冗余,通常用純遞歸
  • 存儲已經計算過的結果,通常用數組和字典
  • 編程時通常采用自底向上思想(遞推)

2、走臺階問題

**題目:**有一座10級臺階的樓梯,從下往上走,每跨一步只能向上1級或者2級臺階。要求用程序來求出一共有多少種走法。

遞歸解法:

int solve(int n) {if(n < 1)return 0;if(n == 1)return 1;if(n == 2)return 2;return solve(n-1)+solve(n-2); }

備忘錄解法:

int solve(int n,HashMap<Interger, Interger>map) {if(n < 1)return 0;if(n == 1)return 1;if(n == 2)return 2;if(map.contains(n))return map.get(n);else{int value = solve(n-1)+solve(n-2);map.put(n, value);return value;} }

動態規劃解法:

int solve(int n,HashMap<Interger, Interger>map) {if(n < 1)return 0;if(n == 1)return 1;if(n == 2)return 2;int a = 1;int b = 2:int temp = 0;for(int i=3; i<=n; i++){temp = a + b;a = b;b = temp;}return temp; }

題目改為一次最多能走k階臺階

思路:其實是一樣的,只要把邊界和遞歸式擴展到 k 即可

// 邊界條件, 轉化為總共 k 階臺階,可以任意走,到達k階有2^(k-1)種走法 num[0] = 1 for(int i=1; i =< k; ++i)num[i] = power(2, i-1);// 遞推 for(int j = k+1; j<n+1; ++j) {z = 1;while(z < k){num[j] += num[j-z];z += 1;} }

3、打家劫舍問題

**題目:**偷商店,不能連續偷兩家,求偷的總額最大

備忘錄解法:

vector<int> save; int solve(vector<int>& nums, int n) {if(n < 0)return 0;if(save[n] >= 0)return save[n];save[n] = max(solve(nums, n-2)+nums[n], solve(nums, n-1));return save[n]; } int rob(vector<int>& nums) {int len = nums.size();for(int i=0; i<len; i++)save.push_back(-1);return solve(nums, len-1); }

動態規劃解法:

int rob(vector<int>& nums) {int n = nums.size(); if(n == 0)return 0;if(n == 1)return nums[0];vector<int> save(n, -1);save[0] = nums[0];save[1] = max(nums[0], nums[1]);for(int i=2; i<n; ++i)save[i] = max(nums[i]+save[i-2], save[i-1]);return save[n-1];

4、01背包問題

題目: 給定 n 種物品和一個容量為 C 的背包,物品 i 的重量是 wi,其價值為 vi ,應該如何選擇裝入背包的物品,使得裝入背包中的物品的總價值最大?

// 下標為0的元素,沒有用到,置為0 int v[N]={0,8,10,6,3,7,2}; int w[N]={0,4,6,2,2,5,1}; int n=6,c=12;int solve() {// 需要知道的初始值是 m[i][0],m[0][j] 都等于0,所以數組都初始化為0int m[n+1][c+1] = {0};for(int i=1;i<=n;i++){for(int j=1;j<=c;j++){if(j>=w[i])m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]); elsem[i][j]=m[i-1][j];}}return m[n][c]

可以進一步壓縮空間,只用2x(c+1)或1x(c+1)大小的數組:

# 2x(c+1)數組 int m[2][c+1] = {0}; m[i%2][j]=max(m[(i-1)%2][j],m[(i-1)%2][j-w[i]]+v[i]); # 1x(c+1)大小的數組 int m[c+1] = {0}; m[j]=max(m[j],m[j-w[i]]+v[i]);

5、硬幣找零

題目: 硬幣的種類值列表 coin_list,要找零錢 change 元,問最少需要幾個硬幣?

遞歸解法:

def find_coins(coin_list, change):min_coins = changeif change in coin_list:return 1else:for i in [c for c in coin_list if c <= change]:num_coins = 1 + find_coins(coin_list, change-i)if num_coins < min_coins:min_coins = num_coinsreturn min_coinsprint(recDC([1,5,10,25], 63)

備忘錄解法:

# save_list 緩存已經算過的零錢最少找幣數,列表大小=最初需要找零的值+1,初始值都=0 def find_coins(coin_list, change, save_list):min_coins = changeif change in coin_list:return 1elif save_list[change] > 0:return save_list[change]else:for i in [c for c in coin_list if c <= change]:num_coins = 1 + find_coins(coin_list, change-i, save_list)if num_coins < min_coins:min_coins = num_coinssave_list[change] = min_coinsreturn min_coinsprint(recDC([1,5,10,25], 63, [0]*64))

動態規劃解法:

# 遞推 def find_coins(coins_list, change, min_coins_list):for num in range(change+1):num_coins = numfor j in [c for c in coins_list if c <= num]:if min_coins_list[num-j] + 1 <= num_coins:num_coins = min_coins_list[num-j]+1min_coins_list[num] = num_coinsreturn min_coins_list[change]print(find_coins([1, 5, 10, 25], 63, [0]*64))

GOOD LUCK!


總結

以上是生活随笔為你收集整理的数据结构与算法(C++)– 动态规划(Dynamic Programming)的全部內容,希望文章能夠幫你解決所遇到的問題。

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