演算法導論鋼條切割問題
阿新 • • 發佈:2019-01-10
鋼條切割
思路:
1、先考慮,鋼條總長度為0時,總價值為0;
2、考慮,鋼條總長度為1時,此時無法切割,總價值為1;
3、鋼條長為2時,兩種情況:不切割,中間切割一次,比較誰大,取大的方案(要用到上面的結果2);
...
總結:長度為i的鋼條,最左端切割的位置為k,那麼總價值如下遞推式:
dp[i] = max(dp[i−k]+price[k])(i>0,1<= k<=i )
dp[0] = 0(i=0)
#include <iostream>
using namespace std;
int price[11] = {0,1,5,8,9,10,17,17,20 ,24,30};
int N = 10;
int a[11];
int solution2(int m){
int dp[11];
int ans = 0;
// memset(dp,0, sizeof(dp));
dp[0] = 0;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= i; ++j) {
// dp[i] = max(dp[i],price[j]+dp[i-j]);
ans = max(ans,price[j]+dp[i-j]);
}
dp[i] = ans;
}
return dp[m];
}
int solution(int i,int j){
int ans = 0;
if(i >= j)
return 0;
else{
// ans = price[j-i];//此處為什麼要單獨拿出來寫???
//上面這句是第一次寫錯了,下面的迴圈寫的是k = i,導致遞迴會一直在solution(i,j)上無線死迴圈。然後加了上面的句子處理初始情況,把下面k從i+1開始,其實上面的句子就是k = j時的特例,不需要單獨拿出來
for (int k = i+1; k <= j; ++k) {
ans = max(ans,price[k-i] + solution(k,j));
// return ans;
}
return ans;//由於之前把這個地方寫錯了,導致很多錯誤不能理解
}
}
//此處是用的長度做遞迴引數,由此也能引發思考,明顯使用長度做引數程式碼要好寫,考慮的東西也更少!
int solution1(int n){
// int ans = 0;
if(a[n] > 0) return a[n];
if(n == 0)
return 0;
else{
// ans = price[n];
for (int k = 1; k <= n; ++k) {
a[n] = max(a[n],price[k] + solution1(n-k));
// return ans;
}
return a[n];
}
}
/*
* output:
第一種解法:
1 5 8 10 13 17 18 22 25 30
第二種解法:
1 5 8 10 13 17 18 22 25 30
第三種解法:
1 5 8 10 13 17 18 22 25 30
*/
int main() {
cout << "第一種解法: " << endl;
for (int j = 2; j <= 11; ++j) {
cout << solution(1,j) << " ";
}
cout << endl << "第二種解法: " << endl;
for (int i = 1; i <= 10; ++i) {
memset(a,0, sizeof(a));
cout << solution1(i) << " ";
}
cout << endl << "第三種解法: " << endl;
for (int k = 1; k <= 10; ++k) {
cout << solution2(k) << " ";
}
return 0;
}