📜  代数表达式的最大值和最小值

📅  最后修改于: 2021-09-17 07:16:25             🧑  作者: Mango

给定形式为 (x 1 + x 2 + x 3 + . . + x n ) * (y 1 + y 2 + . . . + y m ) 的代数表达式,并且
(n + m) 个整数。使用给定的表达式查找最大值和最小值
整数。

例子 :

Input : n = 2, m = 2
        arr[] = {1, 2, 3, 4}
Output : Maximum : 25 
         Minimum : 21
The expression is (x1 + x2) * (y1 + y2) and
the given integers are 1, 2, 3 and 4. Then
maximum value is (1 + 4) * (2 + 3) = 25 
whereas minimum value is (4 + 3) * (2 + 1) 
= 21.

Input : n = 3, m = 1
        arr[] = {1, 2, 3, 4}
Output : Maximum : 24 
         Minimum : 9

一个简单的解决方案是考虑 n 个数字和剩余 m 个数字的所有可能组合并计算它们的值,从中可以得出最大值和最小值。
下面是一个有效的解决方案
这个想法基于有限的 n, m, x1, x2, .. y1, y2, .. 假设 S 是表达式中所有 (n + m) 个数字的总和,X 是 n表达式左侧的数字。显然,表达式右边的 m 个数字之和将表示为 (S – X)。从给定的 (n + m) 数字中可以有许多可能的 X 值,因此问题简化为简单地迭代 X 的所有值并跟踪 X * (S – X) 的最小值和最大值。
现在,问题相当于找到 X 的所有可能值。由于给定的数字在 -50 到 50 的范围内,并且 (n + m) 的最大值是 100,因此 X 将位于 -2500 到 2500 之间,即结果总共 5000 个 X 值。我们将使用动态规划方法来解决这个问题。考虑一个 dp[i][j] 数组,它的值可以是 1 或 0,其中 1 表示通过从 (n + m) 个数字中选择 i 个数字,X 可以等于 j,否则为 0。然后对于每个数字 k,如果 dp[i][j] 是 1,那么 dp[i + 1][j + k] 也是 1,其中 k 属于给定的 (n + m) 个数字。因此,通过遍历所有 k,我们可以通过选择总共 n 个数字来确定 X 的值是否可达
下面是上述方法的实现。

C++
// CPP program to find the maximum
// and minimum values of an Algebraic
// expression of given form
#include 
using namespace std;
 
#define INF 1e9
#define MAX 50
 
int minMaxValues(int arr[], int n, int m)
{
    // Finding sum of array elements
    int sum = 0;
    for (int i = 0; i < (n + m); i++) {
        sum += arr[i];
 
        // shifting the integers by 50
        // so that they become positive
        arr[i] += 50;
    }
 
// dp[i][j] represents true if sum
// j can be reachable by choosing
// i numbers
bool dp[MAX+1][MAX * MAX + 1];
 
    // initialize the dp array to 01
    memset(dp, 0, sizeof(dp));
 
    dp[0][0] = 1;
 
    // if dp[i][j] is true, that means
    // it is possible to select i numbers
    // from (n + m) numbers to sum upto j
    for (int i = 0; i < (n + m); i++) {
 
        // k can be at max n because the
        // left expression has n numbers
        for (int k = min(n, i + 1); k >= 1; k--) {
            for (int j = 0; j < MAX * MAX + 1; j++) {
                if (dp[k - 1][j])
                    dp[k][j + arr[i]] = 1;
            }
        }
    }
 
    int max_value = -INF, min_value = INF;
 
    for (int i = 0; i < MAX * MAX + 1; i++) {
 
        // checking if a particular sum
        // can be reachable by choosing
        // n numbers
        if (dp[n][i]) {
 
            // getting the actual sum as
            // we shifted the numbers by
            /// 50 to avoid negative indexing
            // in array
            int temp = i - 50 * n;
            max_value = max(max_value, temp * (sum - temp));
            min_value = min(min_value, temp * (sum - temp));
        }
    }
    cout << "Maximum Value: " << max_value
         << "\n"
         << "Minimum Value: "
         << min_value << endl;
}
 
// Driver Code
int main()
{
    int n = 2, m = 2;
    int arr[] = { 1, 2, 3, 4 };
    minMaxValues(arr, n, m);
    return 0;
}


Java
// Java program to find the maximum
// and minimum values of an Algebraic
// expression of given form
import java.io.*;
import java.lang.*;
 
public class GFG {
     
    static double INF = 1e9;
    static int MAX = 50;
 
    static void minMaxValues(int []arr,
                              int n, int m)
    {
         
        // Finding sum of array elements
        int sum = 0;
        for (int i = 0; i < (n + m); i++)
        {
            sum += arr[i];
     
            // shifting the integers by 50
            // so that they become positive
            arr[i] += 50;
        }
     
        // dp[i][j] represents true if sum
        // j can be reachable by choosing
        // i numbers
        boolean dp[][] =
             new boolean[MAX+1][MAX * MAX + 1];
     
        dp[0][0] = true;
     
        // if dp[i][j] is true, that means
        // it is possible to select i numbers
        // from (n + m) numbers to sum upto j
        for (int i = 0; i < (n + m); i++) {
     
            // k can be at max n because the
            // left expression has n numbers
            for (int k = Math.min(n, i + 1); k >= 1; k--)
            {
                for (int j = 0; j < MAX * MAX + 1; j++)
                {
                    if (dp[k - 1][j])
                        dp[k][j + arr[i]] = true;
                }
            }
        }
     
        double max_value = -1 * INF, min_value = INF;
     
        for (int i = 0; i < MAX * MAX + 1; i++)
        {
     
            // checking if a particular sum
            // can be reachable by choosing
            // n numbers
            if (dp[n][i]) {
     
                // getting the actual sum as
                // we shifted the numbers by
                /// 50 to avoid negative indexing
                // in array
                int temp = i - 50 * n;
                max_value = Math.max(max_value, temp *
                                        (sum - temp));
                                             
                min_value = Math.min(min_value, temp *
                                        (sum - temp));
            }
        }
         
        System.out.print("Maximum Value: " +
                     (int)max_value + "\n" +
          "Minimum Value: " + (int)min_value + "\n");
    }
 
    // Driver Code
    public static void main(String args[])
    {
        int n = 2, m = 2;
        int []arr = { 1, 2, 3, 4 };
        minMaxValues(arr, n, m);
    }
}
 
// This code is contributed by Manish Shaw
// (manishshaw1)


Python3
# Python3 program to find the
# maximum and minimum values
# of an Algebraic expression
# of given form
def minMaxValues(arr, n, m) :    
    # Finding sum of
    # array elements
    sum = 0
    INF = 1000000000
    MAX = 50
    for i in range(0, (n + m)) :
        sum += arr[i]
 
        # shifting the integers by 50
        # so that they become positive
        arr[i] += 50
 
    # dp[i][j] represents true
    # if sum j can be reachable
    # by choosing i numbers
    dp = [[0 for x in range(MAX * MAX + 1)]
                  for y in range( MAX + 1)]
     
    dp[0][0] = 1
 
    # if dp[i][j] is true, that
    # means it is possible to
    # select i numbers from (n + m)
    # numbers to sum upto j
    for i in range(0, (n + m)) :
         
        # k can be at max n because the
        # left expression has n numbers
        for k in range(min(n, i + 1), 0, -1) :
            for j in range(0, MAX * MAX + 1) :
                if (dp[k - 1][j]) :
                    dp[k][j + arr[i]] = 1
 
    max_value = -1 * INF
    min_value = INF
 
    for i in range(0, MAX * MAX + 1) :
 
        # checking if a particular
        # sum can be reachable by
        # choosing n numbers
        if (dp[n][i]) :
 
            # getting the actual sum
            # as we shifted the numbers
            # by 50 to avoid negative
            # indexing in array
            temp = i - 50 * n
            max_value = max(max_value,
                         temp * (sum - temp))
                                         
            min_value = min(min_value,
                         temp * (sum - temp))
     
    print ("Maximum Value: {}\nMinimum Value: {}"
                 .format(max_value, min_value))
 
# Driver Code
n = 2
m = 2
arr = [ 1, 2, 3, 4 ]
 
minMaxValues(arr, n, m)
 
# This code is contributed by
# Manish Shaw(manishshaw1)


C#
// C# program to find the maximum
// and minimum values of an Algebraic
// expression of given form
using System;
using System.Collections.Generic;
 
class GFG {
     
    static double INF = 1e9;
    static int MAX = 50;
 
    static void minMaxValues(int []arr, int n, int m)
    {
         
        // Finding sum of array elements
        int sum = 0;
        for (int i = 0; i < (n + m); i++)
        {
            sum += arr[i];
     
            // shifting the integers by 50
            // so that they become positive
            arr[i] += 50;
        }
     
    // dp[i][j] represents true if sum
    // j can be reachable by choosing
    // i numbers
        bool[,] dp = new bool[MAX+1, MAX * MAX + 1];
     
        dp[0,0] = true;
     
        // if dp[i][j] is true, that means
        // it is possible to select i numbers
        // from (n + m) numbers to sum upto j
        for (int i = 0; i < (n + m); i++) {
     
            // k can be at max n because the
            // left expression has n numbers
            for (int k = Math.Min(n, i + 1); k >= 1; k--)
            {
                for (int j = 0; j < MAX * MAX + 1; j++)
                {
                    if (dp[k - 1,j])
                        dp[k,j + arr[i]] = true;
                }
            }
        }
     
        double max_value = -1 * INF, min_value = INF;
     
        for (int i = 0; i < MAX * MAX + 1; i++)
        {
     
            // checking if a particular sum
            // can be reachable by choosing
            // n numbers
            if (dp[n,i]) {
     
                // getting the actual sum as
                // we shifted the numbers by
                /// 50 to avoid negative indexing
                // in array
                int temp = i - 50 * n;
                max_value = Math.Max(max_value, temp *
                                          (sum - temp));
                                           
                min_value = Math.Min(min_value, temp *
                                          (sum - temp));
            }
        }
         
        Console.WriteLine("Maximum Value: " + max_value
         + "\n" + "Minimum Value: " + min_value + "\n");
    }
 
    // Driver Code
    public static void Main()
    {
        int n = 2, m = 2;
        int []arr = { 1, 2, 3, 4 };
        minMaxValues(arr, n, m);
    }
}
 
// This code is contributed by Manish Shaw
// (manishshaw1)


PHP
= 1; $k--)
        {
            for ($j = 0; $j < $MAX *
                              $MAX + 1; $j++)
            {
                if ($dp[$k - 1][$j])
                    $dp[$k][$j + $arr[$i]] = 1;
            }
        }
    }
 
    $max_value = -1 * $INF;
    $min_value = $INF;
 
    for ($i = 0; $i < $MAX * $MAX + 1; $i++)
    {
 
        // checking if a particular
        // sum can be reachable by
        // choosing n numbers
        if ($dp[$n][$i])
        {
 
            // getting the actual sum
            // as we shifted the numbers
            // by 50 to avoid negative
            // indexing in array
            $temp = $i - 50 * $n;
            $max_value = max($max_value, $temp *
                                ($sum - $temp));
                                         
            $min_value = min($min_value, $temp *
                                ($sum - $temp));
        }
    }
     
    echo ("Maximum Value: ". $max_value. "\n".
          "Minimum Value: ". $min_value. "\n");
}
 
// Driver Code
$n = 2;
$m = 2;
$arr = [ 1, 2, 3, 4 ];
 
minMaxValues($arr, $n, $m);
 
// This code is contributed by
// Manish Shaw(manishshaw1)
?>


Javascript


输出 :
Maximum Value: 25
Minimum Value: 21

这种方法的运行时复杂度为 O(MAX * MAX * (n+m) 2 )。