动态规划--并不是特定的算法,是一种思想;通常需要整理出一个递推式,如:f(i)=g(i-1)+g(i-2),每一个i称为一个状态,每个状态只跟前面的状态有关系;
跟高中学的递推式是一样的吧。。
题目一:
如这样的三角形:
第一行n为行数;
接下来三行为每层三角形的数字排列;规则是:从第一层往下 每次可以往左或者往右,输出经历点数字和最大的那个;
输出 27
3
9
9 1
9 2 9
27
分析:可以从上往下,也可以从下往上;
这道题从底层往上走;
对三角形用二维数组a[][]记录;a[1][1]代表第一层第一个数字;例子a[3][1]为第三层的第一个数组9;
则 定义一个状态dp[i][j],表示在第i层第j列的已经经过的最大数字;注意是从下往上;
dp[3][1] =9 (只能为9);dp[3][2]=2;dp[3][3]=9;
则dp[2][1] = a[2][1] + max{dp[3][1],dp[3][2]};dp[2][2]=....
所以递推式为:
dp[i][j] = Math.max{dp[i+1][j]+dp[i+1][j+1]}+a[i][j];
自然 最顶层的就是最大的数字和了;
import java.util.Scanner;
public class 捡水果 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int a[][] = new int[n+1][n+1];
int dp[][] = new int[n+1][n+1];
for (int i = 1; i < n+1; i++) {
for (int j = 1; j <= i; j++) {
a[i][j] = input.nextInt();
}
}
input.close();
for (int i = 1; i < n+1; i++) {
dp[n][i] = a[n][i];
}
for (int i = n-1; i >0; i--) {
for (int j = 1; j <= i; j++) {
dp[i][j] = Math.max(dp[i+1][j], dp[i+1][j+1])+a[i][j];
}
}
System.out.println(dp[1][1]);
}
}
计蒜客-蒜头跳木桩:
说有一列树桩:高低不一;如:9 5 8 3 9 4 1
只能跳比等于或小于当前木桩高度;不能回头跳;
问你选一个木桩来跳能跳到最多的木桩;
分析:
如用dp[i]来记录一个状态;看例子:假如跳到8,必然是从9跳过去的;dp[8] = dp[9] + 1;
假如跳到3;那么可能是从9,5,8跳过去的;dp[8] = dp[j] + 1; j为之前比3大的所有数;
则递推式:dp[i]=max{dp[j],j=...}+1;j之前比i都高或者等于的木桩;遍历可得。。
import java.util.Scanner;
public class 蒜头跳木桩 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int high[] = new int[n+1];
for (int i = 1; i < high.length; i++) {
high[i] = input.nextInt();
}
int dp[] = new int[n+1];
for (int i = 1; i < high.length; i++) {
int position = 0;
int temp = -1;
for (int j = 1; j < i; j++) {
if(high[j]>=high[i]){
if (dp[j]>=temp) {
position=j;
temp=dp[j];
}
}
}
dp[i]=dp[position]+1;
}
int max =0;
for (int i = 1; i < dp.length; i++) {
if (dp[i]>=max) {
max=dp[i];
}
}
System.out.println(max);
}
}