问题:现在已知有一个长度为n的切割杆,且1~n长度对应的价值存储在prices[n]数组中,将其进行若干次切割,求其达到的最大价值?
通过问题的叙述我们可以发现,和前一篇讲解的动态规划之二:剪绳子问题很相似,都属于动态规划的内容,因此我们就用动态规划的思想来解决问题。
现在使用形式化语言来描述问题规模的最大价值状态,即f(n)表示长度为n的切割杆的最大价值。prices[n]数组中存储对应长度为1~n的价值并且是随机的,也就是说prices[2]的价值并不比prices[1]的价值大。因此假设我们第一次切割的长度为i,其最大价值为f(i),剩余的切割杆的长度为n-i,其最大价值为f(n-i):
使用具体示例进行分析:
当n=0时,f(0)= 0;
当n=1时,f(1)= prices[0];
当n=2时,f(2)= max( prices[1] , f(1)+f(1) );
当n=3时,f(3)= max( prices[2] , f(1)+f(2) );
当n=4时,f(4)= max( prices[3] , f(1)+f(3) , f(2)+f(2) );
.......
f(n)=max( prices[n-1] , f(1)+f(n-1) , f(2)+f(n-2) , ...,f(i)+f(n-i) ) ( i>=0 && i<n/2 )
由此,我们可以知道状态转移函数为:f(n)= max( prices[n-1] , f(i) *+f(n-i) ) , 其中i的取值范围为(i>0&&i<=n/2)。
程序结果如下:
#include<iostream>
using namespace std;
#define size 100 //表格的大小
int Line_Max(int a[], int n) {
if (n <= 0)
return 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i / 2; j++) //比较的范围为:(1,n/2)
if (a[j] +a[i - j]>a[i])
a[i] = a[j] + a[i - j];
return a[n];
}
int main() {
int table[size] = { 0 };
int prices[size];
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> prices[i];
for (int i = 1; i <= n; i++)
table[i] = prices[i-1];//对表格用prices数组进行初始化,用来存储长度为i的最大乘积值
cout <<"长度为"<<n<<"的最大价值为:"<< Line_Max(table, n) << endl;
return 0;
}