问题描述:试设计一个算法,计算出从三角形的顶到底的一条路径,使该路径经过的数字总和最大,输出最大值和具体路径。
算法构思:采用动态规划的方法自底向上求解较大值,并将每次求的的值保存到一个二维数组中,该数组的行数比原用来记录数字三角形的二维数组的行数少一行,通过该数组可以避免重复计算,且最大值为该数组的第一行第一列元素。另用一个二维数组记录路径,并根据该数组自顶向下找到获得最大值的路径并输出。
代码实现:
package shzsjx;
import java.util.Scanner;
public class shzsjx
{
public static int Max_(int a,int b)//求二者中较大值
{
int max=0;
if(a>=b)
max=a;
else
max=b;
return max;
}
public static void main(String[] args)
{
System.out.print("请输入数字三角形的行数: ");
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt();
int a[][] = new int[n][n];//用来存储原数字三角形的值
for(int i=0;i<n;i++)//为三角形赋初值
{
for(int j=0;j<=i;j++)
{
a[i][j]=scanner.nextInt();
}
}
int [][]b = new int[n-1][n-1];//采用动态规划时,用来记录新数据
int [][]c = new int[n-1][n-1];//用来记录路径,0向下,1向右下
for(int i=n-2;i>=0;i--)
{
for(int j=0;j<=i;j++)
{
if(i==n-2)
{
b[i][j]=a[i][j]+Max_(a[i+1][j],a[i+1][j+1]);//填写新三角形的最后一行
}
else
{
b[i][j]=a[i][j]+Max_(b[i+1][j],b[i+1][j+1]);//填写新三角形的其余行
}
if(a[i+1][j]==a[i+1][j+1] && i<n-2)//若向下走和向右走值一样,就向下试探一步再确定
{
if(b[i+1][j]>b[i+1][j+1])//向下走值大
c[i][j]=0;//向下
else if(b[i+1][j]<b[i+1][j+1])//向右下走值大
c[i][j]=1;//向右下
}
else if(a[i+1][j]!=a[i+1][j+1])
{
if(Max_(a[i+1][j],a[i+1][j+1])==a[i+1][j])//记录原数字三角形向下走值较大的路径,0向下,1向右下(该行的下一行如何走)
c[i][j]=0;//向下
else if(Max_(a[i+1][j],a[i+1][j+1])==a[i+1][j+1])
c[i][j]=1;//向右下
}
}
}
System.out.println("中间过程产生的新三角形为:");
for(int i=0;i<=n-2;i++)
{
for(int j=0;j<=i;j++)
{
System.out.print(b[i][j]+" ");
}
System.out.println();
}
System.out.println("从原数字三角形中可以得到最大值为: "+b[0][0]);
System.out.println("具体路径如下:");
System.out.print(a[0][0]+"->");
int j=0;
for(int i=0;i<=n-2;)//根据数组c记录的路径,找到一条值最大的路径
{
if(c[i][j]==0)
{
System.out.print(a[i+1][j]);
i++;
}
else if(c[i][j]==1)
{
System.out.print(a[i+1][j+1]);
i++;
j++;
}
if(i<=n-2)
System.out.print("->");
}
}
}
运行结果:
注意:在选择第三行的6的下一个元素时,由于向下走和向右下走值一样,所以采用向下试探的方法来确定具体路径,在这里看16和17,由于17大于16,所以6向右下走,而不向下走。
此次分享到此结束,如有问题请多多指教!