最小m段问题

描述:

有n个整数,分成m段。使每一段的和的最小值尽可能的大。

输入:第一行是两个整数n(整数个数),m(分段数),接下来一行是n个整数

输出:输出尽可能大的每一段和的最小值

样例输入:

5 3

4 2 4 5 1

样例输出:

4

 

分析:首先这是一个动态规划的算法。所谓动态规划也就是把待求解的问题分成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。区别于分治法,动态规划的子问题往往是相互不独立的,子问题会被重复计算。这样我们可以先保存已解决的子问题,然后在用到的时候再找出已求的答案,这样就能避免重复计算带来的时间上的浪费。

        动态规划解法:

(说明:以下所有数组下标皆从1开始,不是从0开始,只为方便理解)

用opt数组来记录计算的结果。opt[a][b]代表a个顶点分成b段所得到最优解,即我们要输出的尽可能大的每一段和的最小值。

首先定义一个初始值opt[0][1] = 0;                                     

                        1、当分段数 j = 1 时,也就是分一段时,f[i][1] = f[i - 1][1] + temp[i];

                             其中temp是我们输入的一组数据;

                        2、当分段数 j >= 2 && j <= m时,f[i][j] = max(min(f[i][1] - f[k][1],f[k][j-1]));

                             其中 k 是一个中间变量,其值位于 1 与 i - 1之间, 1 < k < i - 1;

                             i 为数据的个数,即n代表的意义。

下面分享我的代码:C/C++

#include <iostream>
#define myMax(a,b) (((a) > (b)) ? (a) : (b))
#define myMin(a,b) (((a) < (b)) ? (a) : (b))
using namespace std;
int main()
{
    int i,j,k,n, m;
    int temp[51];

    int opt[51][51] = { 0 };
    int Min;
    int Max = 0;
    cin >> n >> m;
    for (i = 1; i <= n; i++)
    {
        cin >> temp[i];
    }
    // 初始化
    opt[0][1] = 0;
    // j = 1的情况
    for (i = 1; i <= n; i++)
    {
        opt[i][1] = opt[i - 1][1] + temp[i];
    }
    Min = opt[n][1];
    // j >= 2 ,j组数,i数的个数,k数据的个数
    for (j = 2; j <= m; j++)
    {
        for (i = j; i <= n; i++)
        {
            Min = 0;
            for (k = 1; k <= i - 1 ; k++)
            {
                Max = myMin(opt[i][1] - opt[k][1], opt[k][j - 1]);
                if (Max > Min)
                    Min = Max;
            }
            opt[i][j] = Min;
        }
    }
    cout << Min << endl;
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值