例题1:数塔取数问题
一个高度为N的由正整数组成的三角形,从上走到下,求经过的数字和的最大值。
每次只能走到下一层相邻的数上,例如从第3层的6向下走,只能走到第4层的2或9上。
该三角形第n层有n个数字,例如:
第一层有一个数字:5
第二层有两个数字:8 4
第三层有三个数字:3 6 9
第四层有四个数字:7 2 9 5
最优方案是:5 + 8 + 6 + 9 = 28
注意:上面应该是排列成一个三角形的样子不是竖向对应的,排版问题没有显示成三角形。
状态定义: Fi,j是第i行j列项最大取数和,求第n行Fn,m(0 < m < n)中最大值。
状态转移方程:Fi,j = max{Fi-1,j-1,Fi-1,j}+Ai,jt
public class Main
{
/*
* 在数字三角形中寻找一条从顶部到底边的路径,
* 使得路径上所经过的数字之和最大。
* 路径上的每一步都只能往左下或者右下走。
* 只需要求出这个最大和即可,不必给出路径。
* 三角形的行数大于1小于等于100,整数为0~99
*
* 输入样例:
* 5 -- 三角形的行数
* 7
* 3 8
* 8 1 0
* 2 7 4 4
* 4 5 2 6 5
*
*/
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
int max = 0;
int[][] dp = new int[n][n];
dp[0][0] = sc.nextInt();
for(int i=1;i<n;i++){
for(int j=0;j<=i;j++){
int temp = sc.nextInt();
if(j==0){
dp[i][j] = dp[i-1][j] + temp;
}
else{
dp[i][j] = Math.max(dp[i-1][j-1], dp[i-1][j]) + temp;
}
max = Math.max(dp[i][j], max);
}
}
System.out.println("结果:"+max);
}
}
}
例题2:编辑距离
编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
例如将kitten一字转成sitting:
sitten (k->s)
sittin (e->i)
sitting (->g)
所以kitten和sitting的编辑距离是3。俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。
给出两个字符串a,b,求a和b的编辑距离。
状态定义:dp[i][j]表示第一个字符串的前i个字母和第二个字符串的前j个字母需要编辑的次数
动态方程:
- if i==0 且 j==0, dp[i][j] = 0
- if i==0 且 j>0, dp[i][j] = j]
- if i>0 且 j==0, dp[i][j] = i
- if i>0 且 j>0, dp[i][j] = min{插入,删除,修改} = min{dp[i-1][j]+1 ,dp[i][j-1]+1,dp[i-1][j-1]+f(i,j)}, 其中f(i,j) = (str1[i] == str2[j]) ? 0 : 1
public class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
while(sc.hasNextLine()){
String str1 = sc.nextLine();
String str2 = sc.nextLine();
int n1 = str1.length();
int n2 = str2.length();
if(n1 == 0 && n2==0){
System.out.println("结果:"+ 0);
continue;
}
if(n1 == 0){
System.out.println("结果:"+ n2);
continue;
}
if(n2 == 0){
System.out.println("结果:"+ n1);
continue;
}
int[][] dp = new int[n1+1][n2+1];
for(int i=0;i<=n1;i++){
dp[i][0] = i;
}
for(int j=0;j<=n2;j++){
dp[0][j] = j;
}
for(int i=1;i<=n1;i++){
for(int j=1;j<=n2;j++){
int temp = (str1.charAt(i-1) == str2.charAt(j-1))? 0:1;
dp[i][j] = Math.min(dp[i-1][j]+1, Math.min(dp[i][j-1]+1, dp[i-1][j-1]+temp));
}
}
System.out.println("结果:" + dp[n1][n2]);
}
}
}
例题3:矩阵取数问题
一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下向右走,求能够获得的最大价值。例如:3 * 3的方格。
1 3 3
2 1 3
2 2 1
能够获得的最大价值为:11。
public class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] dp = new int[N + 1];
int temp = 0;
for (int i = 0; i < N; i++)
{
for (int j = 1; j <= N; j++)
{
temp = sc.nextInt();
dp[j] = Math.max(dp[j], dp[j - 1]) + temp;
}
}
System.out.println("结果:" + dp[N]);
}
}
例题4:最长递增子序列