1.确定dp数组
2.确定递推公式(关键:理解不了再多看看dp数组含义)
3.dp数组初始化(是否需要dp[0]=0或者dp[0]=1)
4.确定遍历顺序
如果求组合数就是外层for循环遍历物品,内层for遍历背包。(无序)
如果求排列数就是外层for遍历背包,内层for循环遍历物品。(有序)
求装满背包有几种方法,递推公式一般都是dp[i]+=dp[i-nums[j]];
5.推导dp数组
1.300. 最长递增子序列
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
//子序列很多,先找到每个递增子序列,再找到最大的
int dp[2510];//以第i个数字结尾的最长子序列
int max1=1;
memset(dp,0,sizeof(dp));
for(int i=0;i<nums.size();i++)//背包以i(限制)结尾最长子序列
{
dp[i]=1;
for(int j=0;j<i;j++)
{
if(nums[j]<nums[i])//递增
{
dp[i]=max(dp[i],dp[j]+1);
max1=max(dp[i],max1);
}
}
}
return max1;
}
};
2.最长公共子序列
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int dp[1010][1010];//长度为text1 i,text2 j的公共子序列
memset(dp,0,sizeof(dp));
for(int i=1;i<=text1.size();i++)
{
for(int j=1;j<=text2.size();j++)
{
if(text1[i-1]==text2[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;
}
else
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[text1.size()][text2.size()];
}
};
3.97. 交错字符串
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
int m=s1.size(),n=s2.size();
if(m+n!=s3.size())
{
return false;
}
int dp[110][110];//i,j交错长度
memset(dp,0,sizeof(dp));//保证交错
dp[0][0]=1;//保证空字符串交错
for(int i=0;i<=m;i++)
{
for(int j=0;j<=n;j++)
{
if(i>0 && dp[i - 1][j] && s1[i - 1] == s3[i + j - 1])//i和j从0开始遍历同时大于0,因为有空字符串的可能
{
dp[i][j] = 1;
}
if(j>0 && dp[i][j - 1] && s2[j - 1] == s3[i + j - 1])
{
dp[i][j] = 1;
}
}
}
return dp[m][n]==1;
}
};
4.