問題描述
某旅遊城市在長江邊開闢了若干個旅遊景點。一個遊船俱樂部在這些景點都設置了遊船出租站,遊客可在這些遊船出租站租用遊船,並在下游的任何一個遊船出租站歸還遊船,從一個遊船出租站到下游的遊船出租站間的租金明碼標價的。你的任務是爲遊客計算從起點站到終點站間的最少租船費用。
輸入
輸入有若干組測試數據,每組測試數據的第一行上有一個整數n,(1<=n<=100),表示上游的起點站0到下游有n個遊船出租站1、2、…、n。接下來有n行,這n行中的第1行有n個整數,分別表示第0站到第1、2、3、…、n站間的遊船租金;第2行有n-1個整數,分別表示第1站到第2、3、4、…、n站間的遊船租金;…;第n-1行有2個整數,表示第n-2站到第n-1、n站間的遊船租金;第n行有1個整數,表示第n-1站到第n站間的遊船租金。一行上兩個整數之間是用空格隔開的。當遊船租金是-1時,表示這兩個站之間無直通航線。兩組測試數據之間無空行。
輸出
對輸入中描述的每組測試數據,先在一行上輸出“Case #:”,其中“#”測試數據的編號(從1開始編)。對輸入文件中的每組測試數據,在輸出文件中輸出一行,內容是該情況下游客從起點站到終點站間的最少租船費用。
輸入樣例
3
2 3 6
1 3
2
3
4 7 9
4 5
6
輸出樣例
Case 1:
5
Case 2:
9
算法思路
用r[i][j]記錄第i站到第j站的直達遊船租金,f[i]記錄從起點第0站到第i站的最少遊船租金。那麼從第0站到第i站有兩種方式到達:
- 直達:r[0][i]
- 中轉:在第k站進行中轉,從第0站到第k站最少租金f[k],從第k站到第i站直達租金r[k][i]
則求解的從第0站到第i站的最少租金爲:
代碼實現
public class Main {
//上游的起點站0到下游有n個遊船出租站
private static int n;
// r[i][j]表示從i直達j+1站的租金
private static int[][] r;
// f[i]表示從0到i站的最少租金
private static int[] f;
public static void main(String[] args) {
// 讀取鍵盤輸入
Scanner sc = new Scanner(System.in);
int count = 0;
while (true) {
count++;
n = sc.nextInt();
r = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
r[i][j] = sc.nextInt();
}
}
System.out.println("Case " + count + ":\n" + solution() + "\n");
}
}
public static int solution() {
// f[0]=0,f[n]表示起點到終點
f = new int[n + 1];
// 從1到n的最少費用,求n要用到n-1,求n-1...
for (int i = 1; i <= n; i++) {
// 0到i直達
f[i] = r[0][i - 1];
for (int k = i - 1; k > 0; k--) {
// 0到i直達或者經過k中轉
f[i] = min(f[i], f[k] + r[k][i - 1]);
}
}
return f[n];
}
}