线性DP(相比之下,有一个模板框架)
最长上升子序列
动态规划O(n^2)的做法
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
const int INF = 1e9 + 10;
int n;
int a[N];
int f[N];//f[i]表示以i结尾的最长递增子序列
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for(int i=1;i<=n;i++)
{
f[i]=1;//这个容易漏掉
for(int j=1;j<=i-1;j++)
{
if(a[j]<a[i])f[i]=max(f[i],f[j]+1);
}
}
int res=-INF;
for(int i=1;i<=n;i++)
{
res=max(res,f[i]);
}
cout << res;
return 0;
}
最长公共子序列
//算法是学习的过程,不是创造的过程
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
const int INF = 1e9 + 10;
int n, m;
char a[N], b[N];
int f[N][N];
int main()
{
cin >> n >> m;
scanf("%s%s", a + 1, b + 1);//这样读入的话就是从1开始
for(int i=1;i<=n;i++)
for (int j = 1; j <= m; j++)
{
if (a[i] == b[j])
{
f[i][j] = f[i - 1][j - 1] + 1;
}
else
{
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
}
}
cout << f[n][m] << endl;
return 0;
}
摘花生(网格类的题目)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
int t;
int r,c;
int hua[N][N];
int dp[N][N];
int main()
{
cin>>t;
while(t--)
{
cin>>r>>c;
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
cin>>hua[i][j];
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
dp[i][j]=max(hua[i][j]+dp[i-1][j],hua[i][j]+dp[i][j-1]);
cout<<dp[r][c]<<endl;
}
return 0;
}
最长上升子序列和摘花生的结合题目
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 55,MOD=1000000007;
int w[N][N];
int f[N][N][13][14];
int n,m,k,c;
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>w[i][j];
w[i][j]++;
}
f[1][1][1][w[1][1]]=1;
f[1][1][0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(i==1&&j==1)continue;
for(int u=0;u<=k;u++)
{
for(int v=0;v<=13;v++)
{
int &val=f[i][j][u][v];
val=(val+f[i-1][j][u][v])%MOD;
val=(val+f[i][j-1][u][v])%MOD;
if(w[i][j]==v&&u>0)
{
for(int c=0;c<v;c++)
{
val=(val+f[i-1][j][u-1][c])%MOD;
val=(val+f[i][j-1][u-1][c])%MOD;
}
}
}
}
}
}
int res=0;
for(int i=0;i<=13;i++)res=(res+f[n][m][k][i])%MOD;
cout<<res<<endl;
return 0;
}