天天看点

《算法:leetCode刷题》动态规划

一.动态规划需要弄清楚的四个方面

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;
}