java课作业一则:动态规划(不优化)

/*

 *1、实验内容:1)第1题:

 *设平面上有一个m×n 的网格,将左下角的网格点标记为(0,0)而右上角的网格点标记为(m,n).某人想从(0,0)出发沿网格线行进到达(m,n).

 *但是在网格点(i,j)处他只能向上行进或者向右行进,向上行进的代价为aij(aij=+∞),向右行进的代价是bij(bij=+∞)

 *试设计一个动态规划算,在这个网格中为该旅行者寻找一条代价最小的旅行路线。编写一个简单的应用程序进行编译、运行;

 *根据网上类似DP问题的思路,为了一致和方便,把左上角标记为起点(0,0),右下角为终点(m,n),每条路径的value(代价)设成了[1,10].

 */

 

import java.util.Scanner;

import java.util.Random;

public class ShortestPath

{

         public static void main(String[] args)

         {

                  //输入行数、列数,用m横n竖表示

                  Scanner matrix = new Scanner(System.in);

                  System.out.println("请输入行数m:");

                  int m = matrix.nextInt() + 1;

                  System.out.println("请输入列数n:");

                  int n = matrix.nextInt() + 1;

                  System.out.println("这是一个" + m + "横" + n + "竖的网格.\n");

                 

                  //①产生一个↓ 的aij矩阵:m行n-1列,value[1,10]随机产生,并且打印.

                  System.out.println("①↓竖着走每一条线的值(aij)如下:");

                  int[][] aij = new int[m - 1][n];//矩阵aij,存放↓路径的value

                  for(int i = 0; i < m - 1; i++)

                  {

                          for(int j = 0; j < n; j++)

                          {

                                   Random rand2 = new Random();

                                   aij[i][j] =(rand2.nextInt(10) + 1);

                                   System.out.printf("%3d",aij[i][j]);

                          }

                          System.out.println("\n");

                  }

                 

                  //②同理产生一个 → 的bij矩阵:m-1行n列,value[1,10]随机产生,并且打印.

                  System.out.println("②→横着走每一条线的值(bij)如下:");

                  int[][] bij = new int[m][n - 1];//矩阵bij,存放→路径的value

                  for(int i = 0; i < m; i++)

                  {

                          for(int j = 0; j < n - 1; j++)

                          {

                                   Random rand1 = new Random();

                                   bij[i][j] =(rand1.nextInt(10) + 1);

                                   System.out.printf("%3d",bij[i][j]);

                          }

                          System.out.println("\n");

                  }

        

                  /*③

                   * 根据动态规划的设计,画出dp矩阵:

                   * 先打印第一横线的每个node的value;

                   * 再打印第一竖线的每个node的value;

                   * 然后,比较(根据上方入口node和对应的向下的abj,左侧入口node和向右的bij,补全dp矩阵.

                   * 最后,打印

                   */

                  int[][] Dp = new int[m][n];//矩阵dp,存放每一node的最短路径值.

                  Dp[0][0] = 0;

                  for(int i = 1; i < m; i++)

                  {

                          Dp[i][0] = Dp[i - 1][0] + aij[i - 1][0];

                                           

                  }

                  for(int j = 1; j < n; j++)

                  {

                          Dp[0][j] = Dp[0][j - 1] + bij[0][j - 1];

                                           

                  }

                  for(int i = 0; i < m - 1; i++)

                  {

                          for(int j = 0; j < n - 1; j++)

                          {

                                   Dp[i+1][j+1] = Math.min(Dp[i + 1][j] + bij[i + 1][j] ,Dp[i][j+1] + aij[i][j + 1]);

                          }

                  }

                  System.out.printf("③到达每个节点的最小值:\n");

                  for(int i = 0; i < m; i++)

                  {

                          for(int j = 0; j < n; j++)

                          {

                                   System.out.printf("%5d",Dp[i][j]);

                          }

                          System.out.println(" \n");

                  }


                   /*

                   * 下面是输出到达节点的最优路径(从"终点"往"左上角起点"倒着再走一遍即可)

                   * 要找个数组s[k]记录每一次的倒着走的过程;要注意到达网格边缘的特殊情况

                   */

                 

                  Scanner node = new Scanner(System.in);

                  System.out.println("请输入交叉点位于第几横:");

                  int a = node.nextInt();

                  System.out.println("请输入交叉点位于第几竖:");

                  int b = node.nextInt();

 

                   if((a <= n) && (a >= 0) && (b <= m) && (b >= 0))//排除用户输入有误的情况

                      {

                        int [] s = new int [a + b - 1];//新建Step数组存放每一步是向下↓还是向右→,长度应该和下面的k一样,但是让k=0很麻烦,故比k长1.

                        int k = a + b - 2;//从起点到终点的步骤数目

                        int i = a - 1;

                        int j = b - 1;

                       

                        while(i != 0 && j != 0)

                        {

                                 if(Dp[i][j] == Dp[i][j - 1] + bij[i][j - 1])//判断(每一个)终点值来自何方,并用1/0记录.

                                 {

                                          s[k] = 0;//0标记为Right

                                          j--;

                                          k--;

                                 }

                                 else

                                 {

                                          s[k]= 1 ;//1标记为Down

                                          i --;  

                                          k --;

                                 }

                                

                                 if(i == 0)//走到第1横了,只能往左方向走(从右侧来).

                                 {

                                          while(j != 0)

                                          {

                                                   s[k] = 0;

                                                   j --;

                                                   k --;

                                          }

                                 }

                                

                                 if(j == 0)//走到第1竖了,只能往上方向走(从下侧来).

                                 {

                                          while(i != 0)

                                          {

                                                   s[k] = 1;

                                                   i --;

                                                   k --;

                                          }

                                 }

                        }

                       

                        System.out.println("具体过程:");//按照上边用s[k]数组存的0/1,打印过程

                        for (i = 1; i <= a + b - 2 ; i ++ )

                        {                

                                 if ( s[i] == 0 )

                                          System.out.println("Right→");

                                           else

                                                   System.out.println("Down↓");

                        }                            

                      }

                     

                   else

                        System.out.println("输入有误");

         }

}


猜你喜欢

转载自www.cnblogs.com/hello2020/p/9842730.html