线性dp
我觉得有如下特点
dp定义是当前元素的结果
最终答案是需要遍历一遍取出来的
不完全是,编辑距离就不是这样的
数字三角形
这里思考如何定义dp
dp[i][j]:i行第j个数,可以达到的最大数值
那么最终的答案就是dp[n][i]里面中的最大值,简单选择一次即可
更新的时候顺带初始化了,这里每个dp[i][j]可以有两条路到达
要么是左上角的数来的,要么是右上角的数来的
感觉写的挺好的吧,y里面有边界情况不知道为什么
#include<iostream>
#include<algorithm>
using namespace std;
const int N=510;
int num[N][N];
int dp[N][N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++) cin>>num[i][j];
}
for(int i=1;i<=n;i++){
dp[i][1]=num[i][1]+dp[i-1][1];
dp[i][i]=num[i][i]+dp[i-1][i-1];
for(int j=2;j<i;j++){
dp[i][j]=num[i][j]+max(dp[i-1][j-1],dp[i-1][j]);
}
}
int k=1;
for(int i=2;i<=n;i++){
if(dp[n][i]>dp[n][k]) k=i;
}
cout<<dp[n][k];
}
最长上升子序列
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int num[N],dp[N];
//这里我一开始定义dp[i]是前i个字符序列的最大上升子序列长度,看似能做
//后面写不下去,dp[i]应该定义为以num[i]结尾的最大上升子序列长度
//这里我总结线性dp一个特点,就是往往最终答案需要我们简单选择一遍
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>num[i];
for(int i=1;i<=n;i++){
dp[i]=1;//以我结尾,至少是1
for(int j=1;j<i;j++){
if(num[i]>num[j]){
dp[i]=max(dp[i],dp[j]+1);
}
}
}
int k=1;
for(int i=1;i<=n;i++){
if(dp[i]>dp[k]) k=i;
}
cout<<dp[k];
}
编辑距离
(想到了去年准备数据挖掘期末考试呢段时间了,当时就在学这个,时间真的好快呀,一年很快就过去了,今天10.21,离考研就最后两个月了)
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int dp[N][N];
//a的前i位变为b的前j位最少需要多少
char a[N],b[N];
int main(){
int n,m;
cin>>n;
// scanf("%s",a+1);
cin>>a;
//这里的字符串输入输出可以通过cin,cout来实现
cin>>m;
// scanf("%s",b+1);
cin>>b;
//初始化
for(int i=1;i<=m;i++) dp[0][i]=i;
for(int i=1;i<=n;i++) dp[i][0]=i;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1);
if(a[i-1]==b[j-1]) dp[i][j]=min(dp[i][j],dp[i-1][j-1]);
else dp[i][j]=min(dp[i][j],dp[i-1][j-1]+1);
//这里我的思路有一些问题,没有先枚举所有情况
//两种一般情况,最后一种情况根据字符是否相等特殊判断
}
}
cout<<dp[n][m];
}
最长公共子序列
本来想不出,通过编辑距离想到了如何去做,这里几乎都没怎么思考,就是仿照编辑距离写出来了
//由编辑距离,想到两个字符串可以使用二维数组
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int dp[N][N];
//a的前i个和b的前j个最长公共序列
char a[N],b[N];
int main(){
int n,m;
cin>>n>>m;
cin>>a;
cin>>b;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
if(a[i-1]==b[j-1]) dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
}
}
cout<<dp[n][m];
}