线性DP:
递推方程有明显的线性关系
比如,背包问题,一行一行的向下求解
例题:
题目链接
898. 数字三角形
给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输入格式
第一行包含整数 n,表示数字三角形的层数。
接下来 n 行,每行包含若干整数,其中第 i 行表示数字三角形第 i 层包含的整数。
输出格式
输出一个整数,表示最大的路径数字和。
数据范围
1≤n≤500,
−10000≤三角形中的整数≤10000
输入样例:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出样例:
30
package luogu.dp.线性DP;
import java.io.*;
public class 数字三角形 {
static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static void main(String[] args) throws IOException {
int n = in();
int[][] a = new int[n+1][n+1];
for ( int i=1; i<=n; i++ ) {
for ( int j=1; j<=i; j++ ) {
a[i][j] = in();
}
}
int[][] dp = new int[n+1][n+2];
for ( int i=0; i<=n; i++ ) {
for ( int j=0; j<=i+1; j++ ) {
// 用MIN会溢出,加负数会向负数溢出
// dp[i][j] = Integer.MIN_VALUE;
dp[i][j] = -10000000;
}
}
dp[1][1] = a[1][1];
for ( int i=2; i<=n; i++ ) {
for ( int j=1; j<=i; j++ ) {
dp[i][j] = Math.max( dp[i-1][j-1]+a[i][j], dp[i-1][j]+a[i][j] );
}
}
int res = Integer.MIN_VALUE;
for ( int i=1; i<=n; i++ ) {
res = Math.max( res, dp[n][i] );
}
out.println(res);
out.flush();
}
public static int in() throws IOException {
in.nextToken();
return (int) in.nval;
}
}
DP问题如果有出现f(i-1)那么下标一般从1开始,这样子不用处理边界问题,并且可以对f(0)设置边界值
DP问题如果无f(i-1),那么下标可以从0开始
**DP问题的时间复杂度为:**状态的个数 X 转移的次数