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

📅  最后修改于: 2021-04-23 19:55:08             🧑  作者: 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之间结果总计为X的5000个值。我们将使用动态编程方法来解决此问题。考虑一个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)
?>


输出 :
Maximum Value: 25
Minimum Value: 21

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