AcWing 898. 数字三角形
#include<bits/stdc++.h>
using namespace std;
const int N=510, INF=-1e9;
int n,a[N][N],f[N][N];
int main(){
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=0;j<=n;j++)
f[i][j]=INF; //因为路径有负数,比如 -6 -4;此时f[2][1]=-10;如果初始化为0的话,f[2][1]=-4了
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
f[i][j]=max(f[i-1][j-1]+a[i][j],f[i-1][j]+a[i][j]);
}
}
int res=INF;
//一直走到底层,要求找出一条路径,使路径上的数字的和最大
for(int i=1;i<=n;i++) res=max(res,f[n][i]);
cout<<res<<endl;
return 0;
}
复杂度: O ( n 2 ) O(n^2) O(n2)
AcWing 897. 最长公共子序列
给定两个长度分别为 N 和 M 的字符串 A 和 B,求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,m,f[N][N];
char a[N],b[N];
int main(){
cin>>n>>m>>a+1>>b+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
f[i][j]=max(f[i-1][j],f[i][j-1]);
if(a[i]==b[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+1);
}
cout<<f[n][m]<<endl;
return 0;
}
AcWing 902. 最短编辑距离
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,m,f[N][N];
char a[N],b[N];
int main(){
cin>>n>>a+1>>m>>b+1;
for(int i=1;i<=n;i++) f[i][0]=i;
for(int i=1;i<=m;i++) f[0][i]=i;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++){
f[i][j]=min(f[i-1][j]+1,f[i][j-1]+1);
if(a[i]==b[j]) f[i][j]=min(f[i][j],f[i-1][j-1]);
else f[i][j]=min(f[i][j],f[i-1][j-1]+1);
}
}
cout<<f[n][m]<<endl;
return 0;
}
区间DP
定义状态时是定义了一个区间
AcWing 282. 石子合并
计数类DP
AcWing 900. 整数划分
一个是去掉1个1不影响数量,另一个是去掉j个1不影响数量