钢条切割问题
问题描述:给定一段长度为n英寸的钢条和一个价格表 p i ( i = 1 , 2 … … , n ) p_i(i=1,2……,n) pi(i=1,2……,n),求切割钢条方案,使得收益 r n r_n rn最大。(假设切割工序本身没有成本支出)
价格表样例:
长度 i i i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
价格 p i pi pi | 1 | 5 | 8 | 9 | 10 | 17 | 17 | 20 | 24 | 30 |
假设收益长度为 n n n英寸的最大收益为 r [ n ] r[n] r[n]。其有递推方程
r [ n ] r[n] r[n]= max 1 ≤ i ≤ n { p n , r [ i ] + r [ n − i ] } \max_{1\le i\le n}\{p_n,r[i]+r[n-i]\} max1≤i≤n{pn,r[i]+r[n−i]}
则有如下代码:
代码下载
/**
* 钢条切割问题
*/
#include <iostream>
#include <vector>
using namespace std;
pair<int,vector<int>> RodCutting(vector<int> &p,int n){
vector<int> r(n+1,0);//初始化长度为n+1的数组,长度为0收益为0
vector<vector<int>> s(n+1);//切割方案
for (size_t i = 1; i <= n; i++)
{
r[i] = p[i-1];//初始一刀未切
s[i] = vector<int>(1,i);
for (size_t j = 1; j < i; j++)
{
//求出最佳切割方案
if(r[j]+r[i-j]>r[i]) {
r[i] = r[j]+r[i-j];
vector<int> a = s[j];
for(auto e : s[i-j]) a.push_back(e);//合并切割方案
s[i]=a;
}
}
}
return make_pair(r[n],s[n]);
}
int main(){
//测试价格表
vector<int> p = {1,5,8,9,10,17,17,20,24,30};
auto ans = RodCutting(p,10);
cout<<"最佳收益:"<<ans.first<<endl;
cout<<"切割方案:";
for(auto e : ans.second) cout<<e<<" ";
cout<<endl;
system("pause");
return 0;
}
Reference
《算法导论》第三版,第15章