最长递增子序列(一维)
子序列是可以不连续的。
,dp[i]是i位置以num[i]结尾的最长子序列长度
状态转移方程:
d p [ i ] = m a x ( d p [ i ] , d p [ j ] + 1 ) , j < i 且 满 足 n u m [ i ] > n u m [ j ] dp[i] = max(dp[i],dp[j]+1) ,j<i且满足num[i]>num[j] dp[i]=max(dp[i],dp[j]+1),j<i且满足num[i]>num[j]
代码:
memset(dp,1,sizeof(dp)) //初始化为1,因为自己本身。
for(int i=0;i<n;++i)
for(int j=0;j<i;++j)
{
if(nums[i]>nums[j])
dp[i] = max(dp[i] ,dp[j]+1);
}
之后遍历一篇dp取最大的值就可以了。
最长递增子序列(二维)
一般题目是一个二维的数据,如给信封的长和宽,问最多可以嵌套多少个信封。
思路:
可以统一将信封的长进行升序排列,如果长度一样,就以宽度降序排列。
然后将宽度取出,在宽度中最长递增子序列就是答案。
bool cmp(vector<int>a,vector<int>b)
{
a[0] == b[0]?return a[1]>b[1]:a[0]<b[0] ;
}
sort(nums,nums+n,cmp)
vector<int>ans;
for(int i =0;i<n;++i)
ans.push_back(nums[i][1]);
//然后将这个ans求最长递增子序列。
最大子数组
子数组或子字符串是连续的。
,dp[i]是i位置以num[i]结尾的最大数组和
在dp[i]位置只有两个选择,一个是与前一个数组合并,另一个是自己新建立一个数组。
所以有状态转移方程:
d
p
[
i
]
=
m
a
x
(
d
p
[
i
−
1
]
+
n
u
m
s
[
i
]
,
n
u
m
s
[
i
]
)
dp[i]=max(dp[i-1]+nums[i],nums[i])
dp[i]=max(dp[i−1]+nums[i],nums[i])
dp[0] = nums[0];//因为第一个数字只能选择自己。
for(int i =1;i<n;++i)
dp[i]=max(dp[i-1]+nums[i],nums[i]) ;
//然后遍历一边dp数组,取最大值就是答案了。
跳跃游戏I
题意是:给一个数组nums,nums[i]是在位置i最多能向前跳跃的步数。问能否可以跳跃到最后一个位置。
思路:我们记录在位置i能最多跳跃到的位置,将问题转化为这最大的位置是否比最后一个位置大就好了。
int ans = 0;
for(int i=0;i<n-1;++i)
{
ans = max(ans,i+nums[i]);
if(ans<=i) //说明遇到了0,那么就无法跳了。
return false;
return ans>=n-1;
}
跳跃游戏II
现在问的是跳到最后一个需要的最少跳跃次数。
贪心思路:我们在一个位置上最长能跳跃到的区间上,选出最大的一个跳跃步数就可以。
int end = 0; //站在索引i,最大能跳跃到end
int fartest =0; //从索引[i...end]起跳,最远到的距离。
int jump = 0;
for(int i =0;i<n-1;++i)
{
fartest = max(fartest,i+nums[i]);
if(end = i)
{
jump ++;
end = fartest ;
}
}
01背包
01背包的状态转移方程为
f
[
i
]
[
j
]
=
m
a
x
(
f
[
i
−
1
]
[
j
]
,
f
[
i
−
1
]
[
j
−
w
[
i
]
]
+
v
[
j
]
)
f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[j])
f[i][j]=max(f[i−1][j],f[i−1][j−w[i]]+v[j])
i代表对i件物体做决策,有两种方式—放入背包和不放入背包。
j表示当前背包的容量。
不放入背包时:第i次决策后的最大价值和第i-1次决策时候的价值是一样的(还是原来的那些物体,没多没少)。
放入背包时:第i次决策后的价值为 第i-1次决策时候的价值 加上 当前物体的价值v[j]。物体放入背包后会使背包容量变为 j ,即没放物体之前背包的容量为j - w[i]。想想啊当前背包容量为j,而这个j是在加了w[i]之后得到的,那么i-1时候背包容量不就是j-w[i]嘛
//代码里面将整个f初始化为0
for (int i = 1; i <= n; i++)
{
for (int j = V; j >= 0; j--)
{
if (j >= w[i])//如果背包装得下当前的物体
{
f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[i]);
}
else//如果背包装不下当前物体
{
f[i][j] = f[i - 1][j];
}
}
}
优化,只需要一维数组就好了
//代码里面将整个f初始化为0
for (int i = 1; i <= n; i++)
{
for (int j = V; j >= w[i]; j--)
{
f[j] = max(f[j], f[j - w[i]] + v[i]);
}
}