最大乘数

44 篇文章 0 订阅
17 篇文章 0 订阅

题目:给出N个1-9的数字 (v1,v2,…,vN),不改变它们的相对位置,在中间加入K个乘号和N-K-1个加号,(括号随便加)使最终结果尽量大。因为乘号和加号一共就是N-1个了,所以恰好每两个相邻数字之间都有一个符号。并说明其具有优化子结构性质及子问题重叠性质。(20分)
例如: N=5, K=2,5个数字分别为1、2、3、4、5,可以加成:
1*2*(3+4+5)=24
1*(2+3)*(4+5)=45
(1*2+3)*(4+5)=45

S(T,start,len)表示在T序列中 从start位置开始 len个元素的和
F(T,start,len,num)表示在序列T中,从start位置开始 len个长度的的元素中插入num个乘号的最大值

F(T,start,len,num) = max{ S(T,start,leftlen) * F(T, leftlen,len-leftlen, mulcount-1) }

最优子结构性质: F(T,start,len,num) = max{ S(T,start,leftlen) * F(T, leftlen,len-leftlen, mulcount-1) } 假设F(T, leftlen,len-leftlen, mulcount-1) 不是最大的 则存在
F’ (T, leftlen,len-leftlen, mulcount-1)> F(T, leftlen,len-leftlen, mulcount-1)
S(T,start,leftlen) * F’(T, leftlen,len-leftlen, mulcount-1)> S(T,start,leftlen) * F(T, leftlen,len-leftlen, mulcount-1)
则存在F’(T,start,len,num)> F(T,start,len,num) 则 F(T,start,len,num)不是最大的 与条件矛盾 所以F(T, leftlen,len-leftlen, mulcount-1)是最大的 所以具有最优子结构的性质

                       F(T,1,5,2)

F(T,2 ,5,1) F(T,3,5,1) F(T,4,5,1)

F(T,3,5,0) F(T,4,5,0) F(T,5,5,0)

所以具有子问题的重叠性

// maxnum.cpp : Defines the entry point for the console application.
//
//F(start,len,multinum) 代表从start位置开始 len个元素长度 有multinum个乘号的的最大值
//S(start,len)代表从start位置开始len个元素的和
//F(start,len,multinum)=max{S(start,leftlen)*F(start+leftlen,len-leftlen,multinum-1) 1<=leftlen<=len 
// 如果len-1<multinum 则F(start,len,multinum)=0  
//如果multinum=0 则F(start ,len,multinum)=S(start,len)
#include "stdafx.h"
// maxnum.cpp : Defines the entry point for the console application.
//
//F(start,end,multinum) 代表从start位置开始到end位置结束 有multinum个乘号的的最大值
//S(start,end)代表从start位置开始到end位置结束的和
//F(start,end,multinum)=max{S(start,middle)*F(middle+1,end,multinum-1) start=<middle<=end;
//如果multinum=0 则F(start ,end,multinum)=S(start,end)
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;

class SeekMax
{
public:
    SeekMax(int num );
    SeekMax(SeekMax&s);//copy constructor
    ~SeekMax();
    int Seek();//Seek the max multiplication number
private:
    vector <int> list;
    int multinum;
    int S(int start, int end);
    int F(int start, int end, int m);
};

SeekMax::SeekMax(int num ) 
{
    multinum = num;
    int temp;
    while (1)
    {
        cin >> temp;
        if (temp == -1)break;
        list.push_back(temp);
    }
}

SeekMax::SeekMax(SeekMax&s)
{
    multinum = s.multinum;
    list.clear();
    for (auto a = s.list.begin(); a != s.list.end(); a++)
        list.push_back(*a);
}

SeekMax::~SeekMax()
{
    list.clear();
}

int SeekMax::Seek()
{
    return F(0, list.size()-1, multinum);
}

int SeekMax::S(int start, int end)
{
    int sum = 0;
    for (int i = start; i <=end; i++)
    {
        sum += list[i];
    }
    return sum;
}
int SeekMax::F(int start, int end, int m)
{
    if (start >end)return 0;
    if (end-start+1-1< m)return 0;//从下标start 开始到下标end 最多能放下end-start+1-1个乘法符号  
    int middle, temp, max;

    if (m == 0)//没有乘号的话直接计算加法的总值
        return S(start, end);

    max = 0;
    for ( middle= start; middle<=end; middle++)
    {
        temp = S(start,middle)*F(middle+1, end, m - 1);
            if (temp > max)
                max = temp;

    }
    return max;
}
int main(int argc, char **argv)
{
    SeekMax myseek(2);
    cout << "the max multiplication is " << myseek.Seek() << endl;
    system("pause");
    return 0;
}

拉格朗日乘数法是一种常用的数学优化方法,用于求解带有约束条件的最优化问题。这种方法的基本思想是将原问题转化为一个无约束的问题,通过引入拉格朗日乘子来将约束条件纳入目标函数中。 在使用拉格朗日乘数法求解问题时,首先需要构建一个拉格朗日函数,它由原始目标函数和约束条件组成。然后,通过对拉格朗日函数进行求导,可以得到一组方程,称为拉格朗日方程。 这组方程包含了原始目标函数和约束条件的关系,通过解这组方程,可以求得最优解。在求解的过程中,有时需要对拉格朗日方程进行最大化或最小化。 为什么要先求最大再求最小呢?这是因为在求解过程中,我们需要找到拉格朗日函数的临界点或者鞍点,这些点可能是最优解。而临界点或者鞍点通常是通过求解一阶导数等于零的方程得到的。当我们求解一阶导数时,需要分别对原始目标函数和约束条件进行求导。 通过求解拉格朗日方程,得到的解中可能包含了最优解,但也可能包含其他类型的点,比如局部最小值、局部最大值等。因此,为了确保求得的解是最优解,需要对拉格朗日函数进行最大化或最小化,以确定最优解的位置。 总结起来,求解过程中先求最大再求最小是为了找到拉格朗日函数的临界点或者鞍点,以确定最优解的位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hebastast

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值