线性动态规划入门之数字三角形

P1216 [USACO1.5] [IOI1994]数字三角形 Number Triangles - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目很简单,就是问你从三角形的顶端到达低端的路径上的数字之和最大。怎么办,我们使用自然人的思维可以想到爆搜,就是从顶端开始不断递归直到低端,我们选出所有到达低端的最大值。但很显然,这么做走完了这个数字三角形,我们不仅会出现小段路径重叠问题更会加重时间复杂度。

比较好想的优化是我们使用记忆化存储,走过一次的路径储存起来,到时再使用无需计算。

举个例子

                                      7

                              3              8

                       8            1              0

                 2           7              4               4

        4              5            2              6                     4

如图所示,当我们计算出从1开始到达低端的最大路径时,我们无需从第二行的8开始往下走路径,无需最算一遍1到低端的最大路径,直接调用即可。

那么,虽然记忆化搜索好用,其实效率还是不高。接着我们记忆化搜索的思路,我们来想动规。

假如只有两层,那很显然答案是第二层里选出最大的一个数加第一层即为答案。假设三层呢,那么就是第二层从第三层依次再两个数种选取最大,第一层又在第二层中选取最大。三层四层皆是如此。

所以说我们可以发现我们只关心当前层数的下一层的两个数的最大值,和这两个数的值是如何转变的不关心,而且我们上层改变数字和下层无关,也就是无后向性,因此我们写出dp方程

d=a-1;
for(b=a-1;b>=1;b--) {
	for(c=1;c<=d;c++) {
		dp[b][c]=dp[b][c]+Math.max(dp[b+1][c], dp[b+1][c+1]);
	}
	d--;
}

答案代码:


import java.awt.FontFormatException;
import java.io.BufferedReader; 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.AnnotatedWildcardType;
import java.math.BigInteger;
import java.net.DatagramPacket;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Spliterator.OfPrimitive;
import java.util.function.IntToDoubleFunction;
import java.util.function.LongBinaryOperator;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.management.relation.InvalidRelationTypeException;
import javax.print.attribute.standard.JobMessageFromOperator;
import javax.print.attribute.standard.JobPriority;
import javax.swing.table.TableModel;
import javax.swing.text.TabSet;
import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec;
public class Main {
  public static void main(String[] args) throws IOException  {
Scanner sc=new Scanner(System.in);
BufferedReader br1=new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw1=new PrintWriter(System.out);
int a=sc.nextInt();
int[][] dp=new int[a+1][a+1];
int b,c,d;
d=1;
for(b=1;b<=a;b++) {
	for(c=1;c<=d;c++) {
		dp[b][c]=sc.nextInt();
	}
	d++;
}
d=a-1;
for(b=a-1;b>=1;b--) {
	for(c=1;c<=d;c++) {
		dp[b][c]=dp[b][c]+Math.max(dp[b+1][c], dp[b+1][c+1]);
	}
	d--;
}
System.out.println(dp[1][1]);
 }
}

 

你可能感兴趣的:(动态规划,动态规划,算法,java)