动态规划五部曲:
定含义,定递推,初始化,定顺序,举例验证
-
例题
动态规划五部曲:
定义一个一维数组来记录不同楼层的状态
1.确定dp数组以及下标的含义
dp[i]:爬到i层的方法数
2.根据1确定递推公式
dp[i]=dp[i-1]+dp[i-2]
3.dp数组如何初始化
dp[0]不用管它是几,因为题目说i是正整数;所以初始化dp[1]=1,dp[2]=2,然后从i=3开始递推。
4.确定遍历顺序
从递推公式dp[i]=dp[i-1]+dp[i-2]得知遍历是从前往后。
5.举几个例子推导验证dp数组
代码示例:
#include<iostream>
#include<vector>
using namespace std;
int n;
vector<int> dp(n+1);
int main()
{
dp[1]=1;
dp[2]=2;
cin>>n;
for(int i=3; i<=n; i++)
{
dp[i]=dp[i-1]+dp[i-2];
}
cout<<dp[n]<<endl;
}
-
例题
动态规划五部曲:
1.确定dp数组以及下标的含义
dp[m][n]:在一个m行n列的迷宫中走到final的路径数
2.根据1确定递推公式
dp[m][n]=dp[m-1][n]+dp[m][n-1];
3.dp数组初始化
dp[1][2,3,4,5,,,n]=1,dp[2,3,4,5,,,m][1]=1,dp[2][2]=2
4.确定遍历顺序
由递推公式可知:从上到下,从左到右
5.举例验证推导dp数组
#include<iostream>
#include<vector>
using namespace std;
int m,n;
int main()
{
cin>>m>>n;
vector<vector<int> > dp(m,vector<int>(n,0));
//注意这里的<vector<int> >,右边两个>要加空格,否则被认作operator而报错
for(int i=0; i<m; i++)
{
dp[i][0]=1;
}
for(int i=0; i<n; i++)
{
dp[0][i]=1;
}
//这里要是先按从上到下的顺序赋值,就把m和n互换,然后别忘了同时换i和j,因为ij对应的含义发生了改变
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];
}
}
// for(int i=0; i<m; i++)
// {
// for(int j=0; j<n; j++)
// {
// cout<<dp[i][j]<<" ";
// }
// cout<<endl;
// }
cout<<dp[m-1][n-1]<<endl;
}
Debug测试用代码:
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
cout<<dp[i][j]<<" ";
}
cout<<endl;
}
-
例题
1.定含义
//dp[i][j] 从(0,0)到(i,j)的不同的路径
2.定递推
//if((i,j)!=障碍)
//dp[i][j]=dp[i-1][j]+dp[i][j-1]
//else
//dp[i][j]=0
3.初始化
//dp[0][0,1,2,3,,,j]=0;
//dp[0,1,2,3,,,i][0]=0;
4.定顺序
//由递归顺序可知他就是按照从左到右从上到下的顺序
#include<iostream>
#include<algorithm>
#include<vector>
int m,n;
//1.定含义
//dp[i][j] 从(0,0)到(i,j)的不同的路径
//2.定递推
//if((i,j)!=障碍)
//dp[i][j]=dp[i-1][j]+dp[i][j-1]
//else
//dp[i][j]=0
//3.初始化
//dp[0][0,1,2,3,,,j]=0;
//dp[0,1,2,3,,,i][0]=0;
//4.定顺序
//由递归顺序可知他就是按照从左到右从上到下的顺序
using namespace std;
int main()
{
cin>>m>>n;
vector<vector<int> > data(m,vector<int>(n,0));
vector<vector<int> > dp(m,vector<int>(n,0));
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
cin>>data[i][j];
}
}
//
dp[0][0]=1;
for(int j=1; j<n; j++)
{
if(data[0][j]==1)
{
dp[0][j]=0;
}
else
dp[0][j]=dp[0][j-1];
}
for(int i=1; i<m; i++)
{
if(data[i][0]==1)
{
dp[i][0]=0;
}
else
dp[i][0]=dp[i-1][0];
}
//if((i,j)!=障碍)
//dp[i][j]=dp[i-1][j]+dp[i][j-1]
//else
//dp[i][j]=0
for(int i=1; i<m; i++)
{
for(int j=1; j<n; j++)
{
if(data[i][j]==1)
{
dp[i][j]=0;
}
else
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
// for(int i=0; i<m; i++)
// {
// for(int j=0; j<n; j++)
// {
// cout<<dp[i][j]<<" ";
// }
// cout<<endl;
// }
cout<<dp[m-1][n-1]<<endl;
}
-
例题
1.dp[i]表示数i的拆分后的最大积
2.j从1到i
dp[i]=max(j*(i-j),j*dp[i-j])
3.初始化dp[2]=1
4.顺序从左到右
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
//1.dp[i]表示数i的拆分后的最大积
//2.j从1到i
//dp[i]=max(j*(i-j),j*dp[i-j])
//3.初始化dp[2]=1
//4.顺序从左到右
int main()
{
int n;
cin>>n;
vector<int> dp(n+1);
dp[1]=1;
dp[2]=1;
for(int i=3;i<=n;i++)
{
for(int j=1;j<=i;j++)//j的遍历上限当然可以再优化一下,这里就不了
{
dp[i]=max(dp[i],max(j*(i-j),j*dp[i-j]));
//比较dp[i]为了在递推公式推导的过程中,每次计算dp[i],取最大的而已。
}
}
// for(int i=1;i<=n;i++)
// {
// cout<<dp[i]<<" ";
// }
cout<<dp[n]<<endl;
}
-
例题
//n 物品数
//w 背包重量上限
//w[i] 第i件物品的重量
//value[i] 第i件物品的价值
1.
dp[i][j] 从下标0~i的物品任取,放到容纳重量为j的背包,价值总和最大是多少
2.
//dp[i][j]=dp[i-1][j]
//dp[i][j]=dp[i-1][j-w[i]]+value[i]
3.
最左行,都是零,最上一行,有变化。
4.
左上方到右下方
#include<iostream>
#include<algorithm>
#include<vector>
//纯01背包
//n 物品数
//w 背包重量上限
//w[i] 第i件物品的重量
//value[i] 第i件物品的价值
//dp[i][j] 从下标0~i的物品任取,放到
// 容纳重量为j的背包,价值总和
// 最大是多少
//dp[i][j]=dp[i-1][j]
//dp[i][j]=dp[i-1][j-w[i]]+value[i]
using namespace std;
int main()
{
int a[]={1,3,4};
int b[]={15,20,30};
vector<int> weight(a,a+3);
vector<int> value(b,b+3);
int max_weight=4;
int n=weight.size();
vector<vector<int> > dp(n,vector<int>(max_weight+1,0));
//第一行赋值,第一列不用赋值
for(int j=weight[0];j<=max_weight;j++)
{
dp[0][j]=value[0];
}
for(int i=1;i<weight.size();i++)
{
for(int j=0;j<=max_weight;j++)
{
if(j<weight[i])
dp[i][j]=dp[i-1][j];//排除j-weight[i]为负数出错的情况
else
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
}
}
// for(int i=0;i<weight.size();i++)
// {
// for(int j=0;j<=max_weight;j++)
// {
// cout<<dp[i][j]<<" ";
// }
// cout<<endl;
// }
cout<<dp[weight.size()-1][max_weight]<<endl;
}
-
例题
参考于公众号:代码随想录