- 最长公共子序列
题目链接
> 注意dp数组的初始化问题 主要看减的 i-1 j-1的位置,若从0开始就会读到随机数据
#include <iostream>
#include <string>
using namespace std;
const int N=1000+10;
string ss1,ss2;
int f[N][N];
int main(){
int n,m;
cin>>n>>m;
cin>>ss1>>ss2;
string s1,s2;
s1+=" ";
s1+=ss1;
s2+=" ";
s2+=ss2;
ss1=s1;
ss2=s2;
for(int i=1;i<ss1.size();i++){
for(int j=1;j<ss2.size();j++){
f[i][j]=f[i-1][j-1];
int aa=max(f[i-1][j],f[i][j-1]);
f[i][j]=max(f[i][j],aa);
if(ss1[i]==ss2[j])
f[i][j]=max(f[i-1][j-1]+1,f[i][j]);
}
}
cout<<f[ss1.size()-1][ss2.size()-1];
return 0;
}
- 最长上升子序列
题目链接
以最后一个结尾,所以最后一个不变,变的部分是1 ~ i-1 ;
所以从i-1中的最长加上1则是以a[i]结尾的最长。
i-1中的最长需要遍历一次f[1]-f[i-1]寻找出最长的,因此需要添加一层循环。
特殊情况,是递减序列,所以长度为1,因此进入第二层循环前可以先设置为1,因为最小的值是1
#include <iostream>
#include<algorithm>
using namespace std;
int n;
int res=0;
int arr[1000 +10];
int f[1000 +10];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
for(int i=1;i<=n;i++){
f[i]=1;
for(int j=1;j<i;j++){
if(arr[i]>arr[j])
f[i]=max(f[i],f[j]+1);
}
}
int res=0;
for(int i=1;i<=n;i++){
res=max(res,f[i]);
}
cout<<res;
return 0;
}
- 最大上升子序列和
题目链接
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1000 ;
int a[N];
int f[N];
int m[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
f[1]=a[1];
for(int i=2;i<=n;i++){
f[i]=a[i];
for(int j=1;j<i;j++){
if(a[i]>a[j])
f[i]=max(f[i],f[j]+a[i]);
}
}
int res=-1;
for(int i=1;i<=n;i++){
res=max(res,f[i]);
}
cout<<res;
return 0;
}
- 登山(分解成两个最长上升子序列)
题目链接
注意分成两种子序列后,顺序是相反的。
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1000 +2;
int a[N];
int b[N];
int f[N];
int f1[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
b[n+1-i]=a[i];
}
for(int i=1;i<=n;i++){
f[i]=1;
for(int j=1;j<i;j++){
if(a[i]>a[j])
f[i]=max(f[i],f[j]+1);
}
}
for(int i=1;i<=n;i++){
f1[i]=1;
for(int j=1;j<i;j++){
if(b[i]>b[j])
f1[i]=max(f1[i],f1[j]+1);
}
}
int res=0;
for(int i=1;i<=n;i++){
res=max(res,f1[n-i+1]+f[i]);
}
cout<<res-1;
return 0;
}
- 怪盗基德的滑翔翼
题目链接
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100+10;
int a[N];
int f1[N];
int f[N];
int main(){
int n;
int nn;
cin>>nn;
while(nn--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
f[i]=1;
f1[i]=1;
for(int j=1;j<i;j++){
if(a[i]<a[j])
f[i]=max(f[i],f[j]+1);
if(a[i]>a[j])
f1[i]=max(f1[i],f1[j]+1);
}
}
int res=0;
for(int i=1;i<=n;i++){
res=max(res,f[i]);
}
int res1=0;
for(int i=1;i<=n;i++){
res1=max(res1,f1[i]);
}
cout<<max(res,res1)<<endl;
}
return 0;
}
- 最大子序和(最长上升子序列和,以a[i]结尾)
题目链接
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int f[nums.size()+10];
f[0]=nums[0];
for(int i=1;i<nums.size();i++){
f[i]=max(f[i-1]+nums[i],nums[i]);
}
sort(f,f+nums.size());
return f[nums.size()-1];
}
};