一.动态规划需要弄清楚的四个方面
1.确认原问题与子问题 2.确认状态 3.确认边界状态的值 4.确定状态转移方程。
二.由易入难,做几道动态规划的题目
1.爬楼梯问题,每次能爬1级台阶或者2级台阶,问爬n级台阶有多少种爬法?
解题思路:可以采用回溯法也可以采用更高效的动态规划法
回溯法实现代码:
#include<iostream>
using namespace std;
class Solution{
public:
int climbStairs(int n){
if(n==1||n==2){
return n;
}
return climbStairs(n-1)+climbStairs(n-2);
}
};
int main()
{
Solution solve;
cout<<solve.climbStairs(4)<<endl;
return 0;
}
动态规划实现代码:
#include<iostream>
#include<vector>
using namespace std;
class Solution{
public:
int climbStairs(int n){
vector<int>dp(n+3,0);
dp[1]=1;
dp[2]=2;
for(int i=3;i<=n;i++){
dp[i]=dp[i-1]+dp[i-2];
}
return dp[n];
}
};
int main()
{
Solution solve;
cout<<solve.climbStairs(6)<<endl;
return 0;
}
二.有一个盗贼到一个街道里面偷东西,东西的价值存放在一个数组中,规定不能盗取相邻两家的东西,否则就会触发警报。问盗贼能够盗取东西的最大价值是多少呢?例如,物体的价值value[4]={1,3,5,7},那么盗贼能够盗取的物体最大价值为10=3+7.
解题思路:每件物体要么被选,要么不被选。被选的前提是相邻的物体没有被选且选后物体价值要为最大。
dp[i]表示前i个物体的最大价值,那么dp[1]=nums[1], dp[2]=max(dp[1],nums[2]]), dp[3]=max(dp[2],dp[1]+nums[3]])
状态转移方程:dp[i]=max(dp[i-1],dp[i-2]+nums[i])
实现代码:
#include<iostream>
#include<vector>
using namespace std;
class Solution{
public:
int stealThing(vector<int>&nums){
int n=nums.size();
if(n==0)
return 0;
if(n==1)
return nums[1];
vector<int>dp(n,0);
dp[0]=nums[0];
dp[1]=max(dp[1],nums[1]);
for(int i=2;i<n;i++){
dp[i]=max(dp[i-1],dp[i-2]+nums[i]);
}
return dp[n-1];
}
};
int main()
{
Solution solve;
int a[6]={5,2,6,3,1,7};
vector<int>b(a,a+6);
cout<<solve.stealThing(b)<<endl;
return 0;
}