钢条切割问题,递归方法实现:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int cutRod(int *p, int n)
{
if (n == 0)
return 0;
int q = -1;
for(int i = 1; i <= n; i++)
q = max(q, p[i]+cutRod(p, n-i));
return q;
}
//自顶向下辅助函数
int memoizedCutRodAux(int *p, int n, int *r)
{
if (r[n] >= 0)
return r[n];
int q = -1;
if (n == 0)
q = 0;
else
{
for (int i = 1; i <= n; i++)
q = max(q, p[i]+memoizedCutRodAux(p, n-i, r));
}
r[n] = q;
return q;
}
//带备忘录的自顶向下,用r[i]记录已经求出的最优解,避免重复调用
int memoizedCutRod(int *p, int n)
{
int r[11] = {};
for (int i = 0; i <= n; i++)
r[i] = -1;
int q = memoizedCutRodAux(p, n, r);
return q;
}
//自底向下
int bottomUpCutRod(int *p, int n)
{
int r[11] = {0};
int q;
for (int j = 1; j <= n; j++)
{
q = -1;
for (int i = 1; i <= j; i++)
q = max(q, p[i]+r[j-i]);
r[j] = q;
}
return r[n];
}
//下面使用的是vector...都生疏了...T_T
//r[]: 记录最优解
//s[]:记录最优解的第一段的钢条的切割长度
pair<vector<int>, vector<int> >
extendedBottomUpCutRod(vector<int> p, int n)
{
vector<int> r, s(p.size());
int q = -1;
r.push_back(0);
for (int j = 1; j <= n; j++)
{
q = -1;
int i;
for (i = 1; i <= j; i++)
{
if (q < p[i] + r[j-i])
{
q = p[i] + r[j-i];
s[j] = i;
}
}
r.push_back(q);
}
return make_pair(r, s);
}
void printCutRodSolution(vector<int> p, int n)
{
pair<vector<int>, vector<int> > vvp =
extendedBottomUpCutRod(p, n);
cout << vvp.first.at(n) << endl;
vector<int> s = vvp.second;
while (n > 0)
{
cout << s[n] << endl;
n -= s[n];
}
}
int main()
{
//使price[0]为0,在程序里不使用,
//只是为了使截断的左右两端与数组下标保持一致,方便代码
int price[] = {0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};
int n;
cout << "请输入n (ctrl+z结束):";
while (cin >> n)
{
cout << "n=" << n << endl;
cout << "普通递归法:\n" << cutRod(price, n) << endl;
cout << "带备忘录的自顶向下法:\n" << memoizedCutRod(price, n) << endl;
cout << "自底向下法:\n" << bottomUpCutRod(price, n) << endl;
vector<int> p(price, price+sizeof(price)/sizeof(price[0]));
cout << "扩展的自底向下法:" << endl;
printCutRodSolution(p, n);
cout << endl << "请输入n (ctrl+z结束): ";
}
system("pause");
return 0;
}
运行结果如下: