一、三步问题
- 我们可以列出一个数组dp[n],在这个数组中的第i位保存的数据就是上i个楼梯有多少种走法,由此我们可以先得到:
dp[1]=1;
dp[2]=2;
dp[3]=4; - 同时我们可以推出状态转移访方程为:dp[i]=(dp[i-1]+dp[i-2]+dp[i-3])
代码如下:
class Solution {
public:
int waysToStep(int n) {
long long dp[1000000]={
0};
dp[1]=1;
dp[2]=2;
dp[3]=4;
for(int i=4;i<=n;i++)
{
dp[i]=(dp[i-1]+dp[i-2]+dp[i-3])%1000000007;
}
return dp[n];
}
};
二、连续数列
- 我们同样可以列出一个数组dp[n],在这个数组中的第i位保存的数据就是第i位能得到的最大连续和,但是和上题不同的是,这里的dp[n]并不是题目要求的最大连续和,只是第n位能取得的最大和,所以真正的答案可能存在1~n之间,这里我们还要用一个变量来记录最大和
- 同样,我们令dp[0]=nums[0],因为这一位的最大和只能是它自己,之后的每一位,要么加上前一位的最大和,要么就不加,然后可推出状态转移方程为:
dp[i]=max(nums[i],dp[i-1]+nums[i]);
代码如下:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int dp[100000]={
0};
int ans=nums[0];
dp[0]=nums[0];
for(int i=1;i<nums.size();i++)
{
dp[i]=max(nums[i],dp[i-1]+nums[i]);
ans=max(dp[i],ans);
}
return ans;
}
};
三、打家劫舍
- 我们同样列出一个数组dp[n],在这个数组中的第i位保存的数据就是第i位能偷到的最大金额,这题的特点是不能连续的偷窃,所以我们的状态转移方程也要进行相应的变换。
- 对于每一个i来说,只有偷和不偷两种选择,如果选择不偷,那么第i位的偷取的最大金额数就会和i-1位的金额数一致,如果选择偷的话,那么第i位的金额就应该是第i-2位的金额数加上第i位可偷取的金额数之和,具体方程如下:
dp[i]=max(dp[i-1],dp[i-2]+nums[i]);
代码为:
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size()==0)
return 0;
if(nums.size()==1)
return nums[0];
int dp[100000]={
0};
dp[0]=nums[0];
dp[1]=max(nums[1],dp[0]);
for(int i=2;i<nums.size();i++)
{
dp[i]=max(dp[i-1],dp[i-2]+nums[i]);
}
return dp[nums.size()-1];
}
};
四、不同路径
- 这题与上面的题目不同的是,这题需要我们建立一个二维的dp数组dp[m][n],相对应的每个dp[i][j]就代表着走到坐标i,j有多少条走法。
- 而我们还需要对这个数组进行一下初始化,由于只能向下或者只能向上,所以我们可以假定一直向左和一直向下,将二维数组的第一列和第一行全部赋值为1,之后我们也可以得到状态转移方程如下:
dp[i][j]=dp[i-1][j]+dp[i][j-1];
代码为:
class Solution {
public:
int uniquePaths(int m, int n) {
int dp[m][n];
if(m==0||n==0)
return 0;
for(int i=0;i<n;i++)
{
dp[0][i]=1;
}
for(int i=0;i<m;i++)
{
dp[i][0]=1;
}
for(int i=1;i<m;i++)
{
for(int j=1;j<n;j++)
{
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
};
五、最小路径和
- 这题和上题很类似,转移方程也十分的相似,因为只能向右或者向下走,所以我们只要考虑向下和向右走哪个能符合题目条件即可,我们可以将上题的转移方程变式一下,就可以得到:
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j];
代码为:
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int dp[grid.size()][grid[0].size()];
dp[0][0]=grid[0][0];
for(int i=1;i<grid.size();i++)
dp[i][0]=dp[i-1][0]+grid[i][0];
for(int i=1;i<grid[0].size();i++)
dp[0][i]=dp[0][i-1]+grid[0][i];
for(int i=1;i<grid.size();i++)
{
for(int j=1;j<grid[0].size();j++)
{
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
return dp[grid.size()-1][grid[0].size()-1];
}
};