目錄
1 問題描述
在n*m格木板中放有一些硬幣,每格的硬幣數目最多為一個,在木板左上方的一個機器人需要收集盡可能多的硬幣並把它們帶到右下方的單元格。每一步,機器人可以從當前的位置向右移動一格或向下移動一格。當機器人遇到一個有硬幣的單元格時,就會將這枚硬幣收集起來。設計一個算法找出機器人能找到的最大硬幣數並給出相應的路徑。
2 解決方案
2.1 動態規划法
本文編碼思想參考自《算法設計與分析基礎》第三版,具體如下:
具體代碼如下:
package com.liuzhen.chapter8; public class RobotCoinCollection { //輸出找到最大硬幣數的路徑 public void getMaxPath(int[][] A){ int rowA = A.length; int columnA = A[0].length; //在數組A最上面一行添加一行元素0,在最左邊一列添加一列元素0 int[][] changeA = new int[rowA+1][columnA+1]; //初始化,各個元素均為0 int[][] maxA = new int[rowA+1][columnA+1]; //用於計算從A[0][0]到達各元素位置收集到的最大硬幣數 for(int i = 0;i < rowA;i++){ for(int j = 0;j < columnA;j++) changeA[i+1][j+1] = A[i][j]; } for(int i = 1;i <= rowA;i++){ for(int j = 1; j <= columnA;j++){ if(maxA[i-1][j] >= maxA[i][j-1]) maxA[i][j] = maxA[i-1][j] + changeA[i][j]; else maxA[i][j] = maxA[i][j-1] + changeA[i][j]; } } //輸出各個元素位置收集到的最大硬幣數 System.out.println("各個元素位置收集到的最大硬幣數:"); for(int i = 1;i <= rowA;i++){ for(int j = 1;j <= columnA;j++) System.out.print(maxA[i][j]+"\t"); System.out.println(); } System.out.println("從左上方到右下方收集到最大硬幣數的路徑(PS:其中元素為-1 表示行走路徑):"); maxA[1][1] = 1; //最左上方位置 maxA[rowA][columnA] = -1; //最右下方位置 int maxI = rowA; int maxJ = columnA; while(maxI >= 1 && maxJ >= 1){ if(maxA[maxI][maxJ-1] >= maxA[maxI-1][maxJ]){ maxA[maxI][maxJ-1] = -1; maxJ = maxJ - 1; } else{ maxA[maxI-1][maxJ] = -1; maxI = maxI - 1; } } for(int i = 1;i <= rowA;i++){ for(int j = 1;j <= columnA;j++) System.out.print(maxA[i][j]+"\t"); System.out.println(); } } public static void main(String[] args){ RobotCoinCollection test = new RobotCoinCollection(); int[][] A ={{0,0,0,0,1,0}, {0,1,0,1,0,0}, {0,0,0,1,0,1}, {0,0,1,0,0,1}, {1,0,0,0,1,0}}; test.getMaxPath(A); } }
運行結果:
各個元素位置收集到的最大硬幣數: 0 0 0 0 1 1 0 1 1 2 2 2 0 1 1 3 3 4 0 1 2 3 3 5 1 1 2 3 4 5 從左上方到右下方收集到最大硬幣數的路徑(PS:其中元素為-1 表示行走路徑): -1 0 0 0 1 1 -1 -1 -1 -1 2 2 0 1 1 -1 -1 -1 0 1 2 3 3 -1 1 1 2 3 4 -1
參考資料:
1.《算法設計與分析基礎》 第3版 Anany Levitin 著 潘彥 譯