您的位置:首页 > 其它

数字序列加入+,*运算符后取得最大值问题; 动态规划;打破传统从决策入手思想;找出问题的特有性质;从例子入手找特点

2014-03-06 21:56 756 查看
假设有一个数组A,里面的元素都大于1的正整数,只采用加号或乘号,不改变数组元素的位置,如何使最后结果最大?比如:

A={2,1,1,1,1,2}那么就用加号结果为8,B={3,1,3}那么就用乘号结果为9。

一开始我想从决策入手,即对每个位置逐次加上+或者*,然后利用回溯方面的思想或者动态规划来做,可是发现一旦遇到*,或者连续*,问题显得很复杂,无法实施。

这个题的特点就是发现特有的性质。 从+断开的地方左右是没有联系的,所以我们应该来安排+号,实现问题的分割。

我们从序列的头开始先找第一个加号,然后计算+左边的乘积,然后计算+右边的最大值。 右边也是同样的问题。

从各种加号的位置分布情况中找到一个最有的值。

[cpp] view
plaincopy

#include <iostream>

using namespace std;

#define MIN -1

class Sum

{

private:

int *result;//动态规划表格,result
表示1....n做加乘综合运算后的最大值

int *path;//在动态规划递推过程中记录加号出现位置

int *arr;//存放num个数字

int num;//数字序列的长度

public:

//构造函数

Sum(int num)//num个数字

{

this->num=num;

result=new int[num+1];//用数组下标的1到n

path=new int[num+1];//记录路径也只用1到n

arr=new int[num+1];//开辟数组存放数字序列,只用1到n

}

//输入数字序列

void input()

{

for(int i=1;i<=num;i++)

{

cin>>arr[i];

}

}

//动态规划求解 ,公式: result
=max { (x[k]*x[k+1]*x[k+2]*....x
)+result[k-1] } ,k取1....n

void maxResult()

{

//初始化reslut[0]=0,即0个数据的最大值为0,初始化result[1]=arr[1],即前1个数据的最大值为本身

result[0]=0;

result[1]=arr[1];

path[1]=1;

//递推求解,最终result
表示前n个数的最大值

int localSum;

int temp;

for(int i=2;i<=num;i++)

{

result[i]=MIN;

localSum=1;

for(int k=i;k>=1;k--)

{

//求x[k]*x[k+1]*.....x[i]

localSum*=arr[k];

//求x[k]*x[k+1]*.....x[i]+result[k-1]

temp=localSum+result[k-1];

//记录k取不同值时所能达到的最大值,并记录断点path[i]

if(temp>result[i])

{

result[i]=temp;

path[i]=k;

}

}

}

}

//打印结果

void display()

{

cout<<"最大*,+结果:"<<result[num]<<endl;

printPath(num);

}

//递归打印整个公式

void printPath(int n)

{

if(path
==1)

{

int j=1;

while(j<=n)

{

cout<<arr[j];

if(j<n)

{

cout<<"*";

}

++j;

}

return;

}

printPath(path
-1);

cout<<"+";

int i=path
;

while(i<=n)

{

cout<<arr[i];

if(i<n)

{

cout<<"*";

}

++i;

}

}

};

void main()

{

Sum sum(6); // 2 1 1 1 1 2

sum.input();

sum.maxResult();

sum.display();

}

思想是动态规划求解 ,

公式: result
=max { (x[k]*x[k+1]*x[k+2]*....x
)+result[k-1] } ,k取1....n

result
表示1...n的最大值

参考的 zyl072 的思路 ,重点理解 X*X*X + X*X*X*X + X + X*X

我们可以从2 1 1 1 1 2的最后往前找,找到一个位置放置一个加号,从这里断开,+ 的右边的是乘积运算 ,右边的乘积+左边的最大值就是整个序列最大值。 左边最大值是同样的子问题 ,会发现有最优子结构性质,动态规划递推就可以了。

关键就是单独的一个X也符合这个公式, 例如2 1 1 1 1 2, 我们可以把加号放在任何一个空位,然后对+右边做乘,对+左边继续递归计算。 例如 2 1 1 1 1 + 2, 这种情况是只有2自己做乘法运算,+左边是同样问题 2 1 1 1 1 ,且与父问题无关 ,这时候举个例子 2 + 1 1 1 1,右边4个1相乘,然后对2递归,2只有自己相乘了就是它本身2 ,公式就变成了 2+1*1*1*1+2 。 现在去看看公式就明白最优子结构了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: