使用Dynamic Programming 的条件
1)优化子结构:一个问题的优化解包含子问题的优化解
2)重叠子问题:在问题的求解过程中,很多子问题被多次使用
算法设计步骤
*分析优化解的结构:划分子问题、优化子结构、子问题重叠性
*建立优化解的代价递归方程
*递归的划分子问题,直至不可划分
*自底向上计算优化解的代价,记录优化解的构造信息
*构造优化解
最短路径问题
1:划分d(S,T)为3个子问题
d(S,T)=min{1+d(A,T), 2+d(B,T), 5+d(C,T)}
2:划分d(A,T), d(B,T), d(C,T)为6个子问题
3:求解最小子问题
d(A,T)=min{4+d(D,T),11+d(E,T)}=min{22,12}=12
d(B,T)=min{9+d(D,T), 5+d(E,T), 16+d(F,T)}=min{27,6,18}=6
d(C,T)=min{2+d(F,T)}=4
4:确定最后最短路径
d(S,T)=min{1+d(A,T), 2+d(B,T), 5+d(C,T)}=min{23,8,9}=8 (S,B,E,T)
动态规划相关问题
1 最长公共子序列
2 矩阵链乘法
3 Optimal Polygon Triangulation
4 0/1背包问题
5 The Optimal Binary Search Trees
6 leetcode上的题368. Largest Divisible Subset,之前没想到用动态规划,后来发现用动态规划更简单
Given a set of distinct positive integers, find the largest subset such that every pair (Si, Sj) of elements in this subset satisfies: Si % Sj = 0 or Sj % Si = 0.
If there are multiple solutions, return any subset is fine.
Example 1:
nums: [1,2,3]
Result: [1,2] (of course, [1,3] will also be ok)
Example 2:
nums: [1,2,4,8]
Result: [1,2,4,8]
class Solution {
public:
vector<int> largestDivisibleSubset(vector<int>& nums)
{
vector<int> result;
if(nums.size()==0)
return result;
int len = nums.size();
vector<int> num_index(len,-1),num_dp(len,1);
int max_dp=1,max_index=0;
//sort(nums.begin(),nums.end(),greater<int>());
sort(nums.begin(),nums.end());
for(int i=0;i<len;i++)
for(int j=i-1;j>-1;j--)
{
if(nums[i]%nums[j]==0 && num_dp[j]+1>num_dp[i])
{
num_dp[i]=num_dp[j]+1;
num_index[i]=j;
}
if(max_dp<num_dp[i])
{
max_dp = num_dp[i];
max_index=i;
}
}
for(;max_index!=-1;max_index=num_index[max_index])
result.push_back(nums[max_index]);
return result;
}
};
相关链接
https://juejin.im/post/5a29d52cf265da43333e4da7
https://blog.csdn.net/u013309870/article/details/75193592