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
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("輸入有誤");
}
}
java課作業一則:動態規劃(不優化)