zoukankan      html  css  js  c++  java
  • 最大字段和的改进最接近0或某一其他固定值的字段和(习题10)

          一、对于最接近0的字段和求解

    1、最接近0就相当于字段和的绝对值最小,此时问题等价于求绝对值最下的字段和。针对此,可以设置一个绝对值结构体,结构如下:

    struct absVal {
        float value; //绝对值
        bool flag;   //标志位,true表示为非负数,否则为负数
    };

      这样,可以将最简单的扫描算法改写成如下:

    简单法求最接近0的字段和
    float maxSum_easy(int n, int* a, int& besti, int& bestj) //最简单的方法,复杂度为O(n^3)
    {
        int i = 0, j = 0, k = 0, sum = 0,sum_t = 0;
        absVal maxSoFar;
        if (a[0]>0)
        {
            maxSoFar.value = a[0];
            maxSoFar.flag = true;
        }
        else
        {
            maxSoFar.value = -a[0];
            maxSoFar.flag = false;
        }
    
        for (i = 0; i < n; ++i)
            for ( j = i; j < n; ++j)
            {
                sum = 0;
                for (k = i; k<=j; ++k)
                    sum += *(a+k);
                sum_t = abs(sum);
                if (sum_t < maxSoFar.value)
                {
                    maxSoFar.value = sum_t;
                    if (sum_t != sum)
                        maxSoFar.flag = false;
                    else
                        maxSoFar.flag = true;
                    besti = i;
                    bestj = j;
                }
            }
        if (maxSoFar.flag)
            return maxSoFar.value;
        else
            return -maxSoFar.value;
    }

      同样可以改写另外两种O(n2)的算法,这里改进动态规划的算法如下:

    动态规划方法求解最接近0字段和
    struct absVal maxSum_sm(int* a, int n) //扫描算法,时间复杂度为O(n)
    {
        absVal maxSoFar, maxendinghere, temp, absa;
        int i =0;
    
        //赋初值
        if (a[0] >= 0)
        {
            maxSoFar.value = a[0];
            maxSoFar.flag = true;
            maxendinghere.value = a[0];
            maxendinghere.flag = true;
        }
        else
        {
            maxSoFar.value = -a[0];
            maxSoFar.flag = false;
            maxendinghere.value = -a[0];
            maxendinghere.flag = false;
        }
        //从1->n-1依次扫描
        for (i = 1; i < n; ++i)
        {
            //求每一个元素的绝对值
            if (a[i] >= 0)
            {
                absa.value = a[i];
                absa.flag = true;
            }
            else
            {
                absa.value = -a[i];
                absa.flag = false;
            }
    
            //求结束位置为i的最接近0的字段和
            if (maxendinghere.flag && absa.flag || !maxendinghere.flag && !absa.flag)
            {
                 temp.value = maxendinghere.value + absa.value;
                 temp.flag = absa.flag;
    
            }
            else if(maxendinghere.value >= absa.value)
            {
                temp.value = maxendinghere.value - absa.value;
                temp.flag = maxendinghere.flag;
            }
            else
            {
                temp.value = absa.value - maxendinghere.value;
                temp.flag = absa.flag;
            }
            if (temp.value < absa.value)
            {
                maxendinghere.value = temp.value;
                maxendinghere.flag = temp.flag;
            }
            else
            {
                maxendinghere.value = absa.value;
                maxendinghere.flag = absa.flag;
            }
            if (maxendinghere.value < maxSoFar.value)
                maxSoFar = maxendinghere;
        }
        return maxSoFar;
    }

    2、课本上所给的答案并不是如此做的,而是设置一个累加数组cum,使得cum[i]=x[0]+...+x[i]。则sum(x[l..u])=cum[u]-cum[l-1],通过定位cum中最接近的两个元素来找出和最接近0的子向量和,而这可以通过排序数组,在O(nlogn)时间内完成。任何能够解决该问题的算法都能用于解决元素“唯一性”问题。 

     二、对于最接近某一个值v的字段和求解方法

    类似于最接近0的方法求解,即求与v绝对值差的绝对值最小的字段和,可以同样实现之。

  • 相关阅读:
    P1536 村村通 题解
    P1551 亲戚题解
    P1185 绘制二叉树 题解
    P3884 [JLOI2009]二叉树问题
    P1087 [NOIP2004 普及组] FBI 树
    P1305 新二叉树题解
    P1229 遍历问题
    P1030 [NOIP2001 普及组] 求先序排列题解
    P1827 [USACO3.4]美国血统 American Heritage 题解
    深度优先搜索dfs 讲解教程
  • 原文地址:https://www.cnblogs.com/lyfruit/p/3026374.html
Copyright © 2011-2022 走看看