在“算法导论”一书中,解决杆切割问题的天真方法可以通过以下重复来描述:
设q是从长度为n的杆获得的最大价格。
让数组价格[1..n]存储给定的价格。 price [i]是长度为i的棒的给定价格。
rodCut(int n)
{
initialize q as q=INT_MIN
for i=1 to n
q=max(q,price[i]+rodCut(n-i))
return q
}
如果我使用以下方法解决该怎么办:
rodCutv2(int n)
{
if(n==0)
return 0
initialize q = price[n]
for i = 1 to n/2
q = max(q, rodCutv2(i) + rodCutv2(n-i))
return q
}
这种做法是否正确?如果是,我们为什么一般使用第一个?为什么会更好?
注意: 我只关心解决这个问题的方法。我知道这个问题表现出最优的子结构和重叠的子问题,并且可以使用动态编程有效地解决。
答案 0 :(得分:0)
第二个版本的问题是它没有使用价格数组。没有递归的基本情况所以它永远不会停止。即使你在n == 1时添加一个返回价格[i]的条件,它也总会将把杆切割成尺寸为1的碎片的结果。
答案 1 :(得分:0)
您的第二种方法绝对正确,其时间复杂度也与第一种相同。 在动态编程中,我们也可以采用相同的方法进行制表。这是我递归的解决方案:
int rodCut (int price[],int n){
if(n<=0) return 0;
int ans = price[n-1];
for(int i=1; i<=n/2 ; ++i){
ans=max(ans, (rodCut(price , i) + rodCut(price , n-i)));
}
return ans;
}
而且,动态编程解决方案:
int rodCut(int *price,int n){
int ans[n+1];
ans[0]=0; // if length of rod is zero
for(int i=1;i<=n;++i){
int max_value=price[i-1];
for(int j=1;j<=i/2;++j){
max_value=max(max_value,ans[j]+ans[i-j]);
}
ans[i]=max_value;
}
return ans[n];
}
答案 2 :(得分:-1)
您的算法看起来几乎正确 - 当n
为奇数时,您需要小心。
但是,它在时间复杂度方面也是指数级的 - 在每次调用rodCutv2
时都会进行两次递归调用。第一种算法使用memoisation(price
数组),因此避免多次计算同一事物,因此更快(它是多项式时间)。
编辑:实际上,第一种算法不正确!它永远不会在prices
中存储值,但我怀疑这只是一个错字而非故意。