总结的部分题目思路与代码,待完善。
【剑指offer-第二版】部分题目与解答【C++版本】
题目:
给一段长度为n的绳子,把绳子剪成m段(m,n都是整数且n>1,m>1,即至少要剪一次),问每段绳子长度的乘积最大是多少?
求解思路:
1.使用动态规划求解:
2.确定子问题:例如绳子的长度为8,那么可以剪成1,7两段,那么此时又要求解长度为7的绳子怎么剪最好。依次类推。
3.确定转移方程,设方程
f(i)
f
(
i
)
表示长度为
i
i
的绳子剪成段之后的最大的乘积。则
f(i)=max(f(j)×f(i−j)),0<j<i
f
(
i
)
=
m
a
x
(
f
(
j
)
×
f
(
i
−
j
)
)
,
0
<
j
<
i
4.为了避免重复计算子问题,我们采用自下而上、从小到大的方式来求解,把先求到的子问题的解储存起来,之后要用到的时候直接进行查表。
5.注意边界条件:虽然有 f(0)=f(1)=0;f(2)=1;f(3)=2; f ( 0 ) = f ( 1 ) = 0 ; f ( 2 ) = 1 ; f ( 3 ) = 2 ; 但是在表中存下来却不是这个值,而应该是: p(0)=0;p(1)=1;p(2)=2;p(3)=3; p ( 0 ) = 0 ; p ( 1 ) = 1 ; p ( 2 ) = 2 ; p ( 3 ) = 3 ; 即在起始条件的时候小问题的最优解并不是我们求解大问题时使用的那个值
可以AC的代码【C++版本】
#include <vector>
#include <iostream>
using namespace std;
int cutRope(int length)
{
if(length <= 1)return 0;
if(length == 2)return 1;
if(length == 3)return 2;
vector<int> backup{0,1,2,3};
for(int i = 4;i != length+1;i++){
int max = 0;
//因为对称的关系,所以只用计算下半段即可
for(int j = 1;j <= (i/2);j++){
int tmp = backup[j]*backup[i-j];
if(tmp > max)
max = tmp;
}
backup.push_back(max);
}
return backup[length];
}
int main()
{
cout << "Please enter the rope length:" << endl;
int n;
while(cin >> n){
cout << cutRope(n) << endl;
}
return 0;
}