蓝桥杯-最大的算式

35 篇文章 0 订阅
25 篇文章 0 订阅

题目大意:给定一个数字序列,要求在其中插入固定个数的*和加号+,使得算式的结果最大。

题目分析:我们用sum[i]保留前i个数的和,用dp[i][j]保留前i个数中含有j个乘号的最大的结果。那么我们最终要求的是dp[N][K]。显然,dp[i][0]=sum[i],因为没有一个乘号,所以就相当于求前n项和。我们自底向上求解。

以题干中的数据为例子:

N = 5, K=2

五个数分别是:1 2 3 4 5

i|j
0
1
2
3
4
1
1
#
#
#
#
2
3
2
#
#
#
3
6
9
#
#
4
10
24
#
#
5
15
#
#
上表表示的是dp[i][j]的值。这张表示如何得到的呢?

首先根据sum[i]可以初始化dp[i][0],然后一列一列求。先求第二列,j=1的情况。

dp[2][1] = dp[1][0] * num[2] = 2

dp[3][1] = max(dp[2][0]*num[3], dp[1][0]*(num[2]+num[3]))

dp[4][1] = max(dp[3][0]*num[4], dp[2][0]*(num[3]+num[4]), dp[1][0]*(num[2]+num[3]+num[4]))

所以,我们得到dp[i][j] = max(dp[i][j], dp[p][j-1]*(sum[i]-sum[p]))   (p表示插入的乘号的位置,1<=p<i)

值得注意的是,结果要设置成long long型,因为位数上限是15位,明显超过了int的范围。

代码展示:

#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;

int main(){
    int N,K;
    cin>>N>>K;
    long long dp[20][20];
    int sum[20];
    int num[20];
    memset(dp,0,sizeof(dp));
    memset(sum,0,sizeof(sum));
    int temp = 0;
    for(int i=1;i<=N;i++){
        cin>>num[i];
        temp += num[i];
        sum[i] = temp;
    }
    for(int i=1;i<=N;i++)
        dp[i][0] = sum[i];
    for(int j=1;j<=K;j++){
        for(int i=1;i<=N;i++){
            if(i>j){         //乘号的数量要小于数字的数量
                for(int p=1;p<i;p++){
                    dp[i][j] = max(dp[i][j],dp[p][j-1]*(sum[i]-sum[p]));
                }
            }
        }
    }
    cout<<dp[N][K]<<endl;
    return 0;
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值