DP 动态规划
解决动态规划问题,要明确状态和转移两个问题
例题1 数字三角形
给出一个数字三角形,从顶点出发每次向下或向右下走,求最大和
定义状态f[i][j]
表示从[1,1]
出发走到[i,j]
所有路径的最大和。
答案就是max(f[n][1...n])
状态:初始状态f[1][1] = a[1][1]
其余为-inf
状态转移方程f[i][j]=max(f[i-1][j],f[i-1][j-1])+a[i][j]
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
int a[105][105];
int f[105][105];
int main()
{
int N;
scanf("%d",&N);
for(int i=1;i<=N;i++)
{
for(int j=1;j<=i;j++)
scanf("%d",&a[i][j]);
}
f[1][1]=a[1][1];
for(int i=1;i<=N;i++)
{
for(int j=1;j<=i;j++)
{
f[i][j]=max(f[i-1][j],f[i-1][j-1])+a[i][j];
}
}
int maxn=0;
for(int i=1;i<=N;i++)
{
if(f[N][i]>maxn)maxn=f[N][i];
}
printf("%d\n",maxn);
return 0;
}
经典问题 最长上升子序列(LIS)
给一个序列,求他的最长上升子序列
状态:f[i]表示以i结尾的上升子序列中的最长长度。
f[i]=max(f[i],f[j]+1) 1<=j<=i
背包问题
01背包
f[i][j]
表示考虑前i
个物品,占用体积为j
,能得到的最大价值
空间优化
1.滚动数组
数组f[i][j]
的取值只与上一行有关
两个数组倒来倒去
X 更新过 O 未更新
XXXXXXXX i-1
OOOOOOO i
↓
XXXXXXXX i-1
XXXXXXXX i
↓
OOOOOOO i+1
XXXXXXXX i
↓
XXXXXXXX i+1
XXXXXXXX i
开数组f[2][maxn]
用f[i%2][i]
代表当前行用f[(i-1)%2][i]
代表上一行
完全背包
与01背包不同,每个物品可以不限制次数取
for(int i=1;i)
刚碰到的小操作
dp的时候经常需要字符串预留出一位
对于string
类型 可以
string str;
str = " "+str;
对于char数组 可以
char str[];
scanf("%s",&str[1]);
贴上今天做D题碰到的manacher(不懂)
https://www.cnblogs.com/fan1-happy/p/11166182.html
https://www.cnblogs.com/cloudplankroader/p/10988844.html