動態規劃做題思路

~Spacetes發表於2020-11-12

動態規劃題目特點

1、計數

  • 有多少種方式走到右下角
  • 有多少種方法選出k個數使得和是sum

2、求最大值最小值

  • 從左上角走到右下角路徑的最大數字和
  • 最長上升子序列長度

3、求存在性

  • 取石子游戲,先手是否必勝
  • 能不能選出k個數使得和是sum

組成部分

一:確定狀態
(1)最後一步
(2)確定子問題
二:轉移方程
三:初始條件和邊界情況
四:計算順序

例題一:

有2元,5元,7元硬幣,求組合成27元硬幣所用最少硬幣數。

一:確定狀態

找出最後一步:最優策略是K枚硬幣a1,a2……ak加起來是27
最後一枚為ak,則前面的面值加起來是27-ak
子問題:最少用多少枚硬幣可以拼出27-ak

二:轉移方程

設狀態f[x]=最少用多少枚硬幣拼出x
對於任何x
f[x]=min{f[x-2]+1,f[x-5]+1,f[x-7]+1}

三:初始條件和邊界情況

  • 初始條件:f[0]=0
  • 定義f[-1]=f[-2]=…=正無窮

四:計算順序

從f[1]開始計算,當計算到f[x]時,f[x-2],f[x-5],f[x-7]都已經得到結果,可以計算

時間複雜度:

O(m×n)

class Solution {
public:
	int coinChange(vector<int> A, int M) {
		int n = A.size();
		vector<int> f(M+1,0);
		f[0] = 0;
		int i, k;
		for (i = 1; i <= M; ++i) {
			f[i] = INT_MAX;
			for (k = 0; k < n; ++k) {
				if (i >= A[k] && f[i - A[k]] != INT_MAX) {
					f[i] = Math.min{ f[i],f[i - A[k]] + 1 };
				}
			}
		}
		if (f[M] == INT_MAX) {
			return -1;
		}
		else {
			return f[M];
		}
		return 0;
	}
};

相關文章