c++實現鋼條切割問題
阿新 • • 發佈:2017-06-12
highlight locks 限制 問題 程序 bottom blog nbsp cnblogs
今天看了算法導論裏面的動態規劃(DP),有個有意思的問題:鋼條切割來獲取最大的收益。
書中講到了幾種求解方法,包括遞歸求解法、備忘錄DP解法、自底向上的解法以及對解的重構。
書中給出不同解法的偽碼,剛好需要練習c++,就有c++來實現DP求解鋼條切割問題。
【遞歸求解】
// 鋼條切割問題 // 自頂向下 遞歸實現 #include <iostream> #include <time.h> using namespace std; int cut_rod(int len, int price_arr[]); int main(int argc, char *argv[]) { clock_t start, finish; double duration; start = clock(); int rod_len = 10; int p_arr[] = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30}; int profit = cut_rod(rod_len, p_arr); cout << "profit = " << profit << endl; finish = clock(); duration = (double)(finish - start)/CLOCKS_PER_SEC; // 單位 s cout << "time cost = " << duration * 1000 << "ms" << endl; return 0; } /* 遞歸調用 cut_rod 函數 * input: 鋼條長度len, 單位鋼條長度價格表price_arr[] * output: 長度為len的鋼條的最佳收益 * * 思想: * 1. 如果len==0,返回收益0 * 2. 否則,把鋼條切割為左邊長度為i 和右邊長度為len-i 的兩段, * 長度為i的一段不在切割,收益為price_arr[i], 右邊部分繼續分解。 * 註意: * 1. 程序存在訪問風險;當輸入長度大於 p_arr[]長度時,會訪問到數組之外的元素; * 因此程序僅對 len < sizeof(p_arr)/sizeof(int) 的數據有效; */ int cut_rod(int len, int price_arr[]) { if (len == 0) return 0; int best_profit = -100; for (int i = 1; i <= len; i++) { best_profit = max(best_profit, price_arr[i] + cut_rod(len-i, price_arr)); } return best_profit; }
【自底向上DP重構解】
自底向上重構解包括自底向上求解法,因此在這兒只傳重構的解法;
文章假定在鋼條長度大於10英寸時,售價仍然為30美元,這樣對輸入的鋼條長度就沒有限制<當然這很不科學>;
/* DP 解決 鋼條切割問題 * 不僅返回長度為len的鋼條的最大收益r[],而且返回切割情況s[](重構的解) * 重構的解也是分析子問題的性質決定的 */ #include <iostream> #include <string.h> #define rod_len 17 #define LEN rod_len + 1 using namespace std; void extend_bottom_up_cut_rod(int len, int price_arr[], int (&r)[LEN], int (&s)[LEN]); void print_cut_rod_solution(int len, int price_arr[], int (&r)[LEN], int (&s)[LEN]); int main(int argc, char *argv[]) { int price[] = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30}; int r[LEN], s[LEN]; memset(r, 0, sizeof(r)); memset(s, 0, sizeof(s)); print_cut_rod_solution(rod_len, price, r, s); return 0; } void extend_bottom_up_cut_rod(int len, int price_arr[], int (&r)[LEN], int (&s)[LEN]) { if (len == 0) return; for (int j = 1; j <= len; j++) { int p = -1000; for (int i = 1; i <= j; i++) // 長度為j的鋼條,切割i { int left_price; if (i > 10) left_price = price_arr[10]; else left_price = price_arr[i]; if (p < left_price + r[j-i]) { p = left_price + r[j-i]; s[j] = i; } } r[j] = p; } } void print_cut_rod_solution(int len, int price_arr[], int (&r)[LEN], int (&s)[LEN]) { extend_bottom_up_cut_rod(len, price_arr, r, s); cout << len << " inch rod price is " << r[len] << endl; cout << "the cut order is "; while (len > 0) { cout << s[len] << " "; len -= s[len]; } }
c++實現鋼條切割問題