問題:
長江游艇俱樂部在長江上設置了n個游艇出租站1,2,3…,n。
游客可以在這些游艇出租站用游艇,並在下游的任何一個游艇出租站歸還游艇。
游艇出租站i到游艇出租站j之間的租金為r(i,j),1<=i<j=n。
試設計一個算法,計算從游艇出租站1到出租站n所需的最少租金。
數據輸入:
第一行表示有n個站點。
接下來n-1行是r( i , j)。
輸入示例(有3個站點,從 1 到 2 要 5,從 1 到 3 要 15,從 2 到 3 要 7):
3
5 15
7
數據輸出:
輸出最從游艇出租站1到出租站n所需的最少租金。
分析:
假設從第 i 站到第 j 站的最優辦法是:從 i 到 k (i<=k<=j),再從 k 到 j ,即 r( i , k )+r( k , j )。則用r( i , k )+r( k , j )代替r( i , j )。
算法思路:
初始化,先定義一個二維數組m[][],將輸入的數據r(i,j)存至m[i][j]。
接着從長度為 2 的開始找較優解(比如說從 1 到 2 就是長度為 2的),直到找到長度為 n 的。具體做法就是分析中所說的。
這樣計算后,所有數據都在 m 數組中了,我們只要輸出 m[1][n]即可。
計算順序:
ps:我發現動態規划的題目都很類似,只要掌握了其特點(我覺得就是用一個數組來表示解,然后在循環中依據子問題不斷計算上一層的父問題),就很好解決。
代碼如下:
#include<iostream> #include<fstream> #include<string>
using namespace std; void main() { ifstream input("input.txt"); ofstream output("output.txt"); int n; int m[200][200] = { 0 }; input >> n; for (int i = 1; i <= n - 1; i++) {//初始化,將所有r(i,j)都先存在數組m中
for (int j = i + 1; j <= n; j++) { input >> m[i][j]; } } for (int r = 2; r <= n; r++) {//接着從長度為 2 的開始找較優解(比如說從 1 到 2 就是長度為 2的),直到找到長度為 n 的
for (int i = 1; i <= n - r + 1; i++) { int j = i + r - 1;// r(i,j)的長度為r
for (int k = i; k <= j; k++) {//在 i 到 j 中找某一站 k,使得r(i,k)+r(k,j)最小
int t = m[i][k] + m[k][j]; if (t < m[i][j]) { m[i][j] = t;//用較優解替換原來的r(i,j)
} } } } output << m[1][n] << endl; input.close(); output.close(); }