📌  相关文章
📜  使最后一列总和最多为任何一列的行最小化为零

📅  最后修改于: 2022-05-13 01:56:05.572000             🧑  作者: Mango

使最后一列总和最多为任何一列的行最小化为零

给定一个由非负整数组成的N * M矩阵mat[][] 。在一次操作中,选择任意行并将所有元素更改为 0。任务是找到所需的最小操作数,使得第M列中的元素之和小于或等于第 j列中的元素之和 对于至少一个“j”(其中 1 ≤“j”≤“M”-1)。

例子:

天真的方法:最简单的方法是尝试所有可能的行组合并制作它们并检查每个组合是否满足条件。

  • 对一些行进行操作,最简单的方法是尝试所有可能的行组合。
  • 矩阵中有' N '行,因此将有(2^N)种方式用于选择要操作的行。
  • 生成所有可能的组合,并为每个组合执行以下操作:
  • 创建原始矩阵mat[][]的副本“ tmp ”。
  • 计算每个组合中的行数,并将相应行中的所有元素标记为 0(仅在 ' tmp ' 中)。
  • 求第M列中元素的总和,设为'sumM'
  • 计算每列的总和(从1 到 'M-1' ),如果这些列的总和大于或等于第M列,则将行数视为答案之一。
  • 在所有组合中,返回我们发现至少一列总和大于或等于第M列的最小大小(最小行数)。

以下是上述方法的实现:

C++
// C++ code to implement the approach
 
#include 
using namespace std;
 
int countMinOp(int n, int m, vector >& mat)
{
    // If all rows are operated, there
    // will be definitely an answer.
    int ans = n;
 
    // Choose all possible combinations of rows.
    for (int i = 0; i < (1 << n); i++) {
 
        // Copying 'mat' to 'tmp'.
        vector > tmp = mat;
 
        // Variable to store the
        // count of rows cleared.
        int cnt = 0;
 
        for (int j = 0; j < n; j++) {
 
            // Check if current row
            // is set in combination.
            if (((i >> j) & 1) == 1) {
 
                // Clear the 'j-th' row.
                cnt++;
                for (int k = 0; k < m; k++) {
                    tmp[j][k] = 0;
                }
            }
        }
 
        int sumM = 0;
        bool flag = false;
 
        // Sum of the 'Mth' column.
        for (int j = 0; j < n; j++) {
            sumM += tmp[j][m - 1];
        }
 
        // Check if there exists
        // some '1' <= 'j' <= 'M-1'
        // such that Sum[j] >= Sum[M].
        for (int j = 0; j < m - 1; j++) {
 
            int sum = 0;
 
            // Calculating the sum
            // of 'jth' column.
            for (int k = 0; k < n; k++) {
                sum += tmp[k][j];
            }
 
            // Check if current column has
            // sum greater than 'Mth' column.
            if (sum >= sumM) {
                flag = true;
                break;
            }
        }
 
        // If condition is satisfied,
        // then check if this is the
        // minimum number of operations.
        if (flag == true) {
            ans = min(ans, cnt);
        }
    }
 
    // Return the final result.
    return ans;
}
 
// Driver Code
int main()
{
    int N = 3;
    int M = 3;
    vector > mat
        = { { 3, 1, 2 }, { 2, 3, 5 }, { 3, 1, 2 } };
    cout << countMinOp(N, M, mat);
    return 0;
}


Java
// Java code to implement the approach
import java.util.*;
public class GFG {
 
  static int countMinOp(int n, int m, int mat[][])
  {
     
    // If all rows are operated, there
    // will be definitely an answer.
    int ans = n;
 
    // Choose all possible combinations of rows.
    for (int i = 0; i < (1 << n); i++) {
 
      // Copying 'mat' to 'tmp'.
      int tmp[][] = mat;
 
      // Variable to store the
      // count of rows cleared.
      int cnt = 0;
 
      for (int j = 0; j < n; j++) {
 
        // Check if current row
        // is set in combination.
        if (((i >> j) & 1) == 1) {
 
          // Clear the 'j-th' row.
          cnt++;
          for (int k = 0; k < m; k++) {
            tmp[j][k] = 0;
          }
        }
      }
 
      int sumM = 0;
      boolean flag = false;
 
      // Sum of the 'Mth' column.
      for (int j = 0; j < n; j++) {
        sumM += tmp[j][m - 1];
      }
 
      // Check if there exists
      // some '1' <= 'j' <= 'M-1'
      // such that Sum[j] >= Sum[M].
      for (int j = 0; j < m - 1; j++) {
 
        int sum = 0;
 
        // Calculating the sum
        // of 'jth' column.
        for (int k = 0; k < n; k++) {
          sum += tmp[k][j];
        }
 
        // Check if current column has
        // sum greater than 'Mth' column.
        if (sum >= sumM) {
          flag = true;
          break;
        }
      }
 
      // If condition is satisfied,
      // then check if this is the
      // minimum number of operations.
      if (flag == true) {
        ans = Math.min(ans, cnt);
      }
    }
 
    // Return the final result.
    return ans;
  }
 
  // Driver Code
  public static void main(String args[])
  {
    int N = 3;
    int M = 3;
    int mat[][]
      = { { 3, 1, 2 }, { 2, 3, 5 }, { 3, 1, 2 } };
    System.out.print(countMinOp(N, M, mat));
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Python3
# Python program for the above approach
def countMinOp(n, m, mat) :
     
    # If all rows are operated, there
    # will be definitely an answer.
    ans = n
 
    # Choose all possible combinations of rows.
    for i in range(0, (1 << n)):
 
        # Copying 'mat' to 'tmp'.
        tmp = mat
 
        # Variable to store the
        # count of rows cleared.
        cnt = 0
 
        for j in range(0, n):
 
            # Check if current row
            # is set in combination.
            if (((i >> j) & 1) == 1) :
 
                # Clear the 'j-th' row.
                cnt += 1
                for j in range(0, m):
                    tmp[j][k] = 0
                 
        sumM = 0
        flag = False
 
        # Sum of the 'Mth' column.
        for j in range(0, n):
            sumM += tmp[j][m - 1]
         
        # Check if there exists
        # some '1' <= 'j' <= 'M-1'
        # such that Sum[j] >= Sum[M].
        for j in range(0, m-1): 
 
            sum = 0
 
            # Calculating the sum
            # of 'jth' column.
            for k in range(0, n):
                sum += tmp[k][j]
             
            # Check if current column has
            # sum greater than 'Mth' column.
            if (sum >= sumM) :
                flag = True
                break
             
        # If condition is satisfied,
        # then check if this is the
        # minimum number of operations.
        if (flag == True) :
            ans = min(ans, cnt)
         
    # Return the final result.
    return ans
 
# Driver Code
N = 3
M = 3
mat = [[3, 1, 2 ], [ 2, 3, 5 ], [ 3, 1, 2 ]]
print(countMinOp(N, M, mat))
 
# This code is contributed by code_hunt.


C#
// C# code to implement the approach
using System;
class GFG {
 
  static int countMinOp(int n, int m, int [,]mat)
  {
     
    // If all rows are operated, there
    // will be definitely an answer.
    int ans = n;
 
    // Choose all possible combinations of rows.
    for (int i = 0; i < (1 << n); i++) {
 
      // Copying 'mat' to 'tmp'.
      int [,]tmp = mat;
 
      // Variable to store the
      // count of rows cleared.
      int cnt = 0;
 
      for (int j = 0; j < n; j++) {
 
        // Check if current row
        // is set in combination.
        if (((i >> j) & 1) == 1) {
 
          // Clear the 'j-th' row.
          cnt++;
          for (int k = 0; k < m; k++) {
            tmp[j,k] = 0;
          }
        }
      }
 
      int sumM = 0;
      bool flag = false;
 
      // Sum of the 'Mth' column.
      for (int j = 0; j < n; j++) {
        sumM += tmp[j,m - 1];
      }
 
      // Check if there exists
      // some '1' <= 'j' <= 'M-1'
      // such that Sum[j] >= Sum[M].
      for (int j = 0; j < m - 1; j++) {
 
        int sum = 0;
 
        // Calculating the sum
        // of 'jth' column.
        for (int k = 0; k < n; k++) {
          sum += tmp[k,j];
        }
 
        // Check if current column has
        // sum greater than 'Mth' column.
        if (sum >= sumM) {
          flag = true;
          break;
        }
      }
 
      // If condition is satisfied,
      // then check if this is the
      // minimum number of operations.
      if (flag == true) {
        ans = Math.Min(ans, cnt);
      }
    }
 
    // Return the final result.
    return ans;
  }
 
  // Driver Code
  public static void Main()
  {
    int N = 3;
    int M = 3;
    int [,]mat
      = { { 3, 1, 2 }, { 2, 3, 5 }, { 3, 1, 2 } };
    Console.Write(countMinOp(N, M, mat));
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Javascript


C++
// C++ code to implement the above approach
 
#include 
using namespace std;
 
int countMinOp(int n, int m,
               vector >& mat)
{
    // If all rows are operated,
    // there will be definitely an
    // answer.
    int ans = n;
 
    // Choose each column one by one.
    for (int i = 0; i < m - 1; i++) {
 
        // Calculate difference of
        // elements in i-th column
        // with final column.
        vector diff;
        for (int j = 0; j < n; j++) {
            diff.push_back(mat[j][i]
                           - mat[j][m - 1]);
        }
 
        // Sort differences in
        // non-decreasing order.
        sort(diff.begin(), diff.end(),
             greater());
     
 
        // Consider differences
        // until sum of differences is
        // non-negative, i.e.,
        // Sum[i] >= Sum[M].
        int sum = 0, k = 0;
 
        while ((k < n) and (sum + diff[k]
                            >= 0)) {
            sum += diff[k];
            k++;
        }
 
        // Remaining elements must
        // be removed. Minimize the answer
        ans = min(ans, n - k);
    }
    return ans;
}
 
// Driver Code
int main()
{
    int N = 3;
    int M = 3;
    vector > mat
        = { { 3, 1, 2 }, { 2, 3, 5 }, { 3, 1, 2 } };
    cout << countMinOp(N, M, mat);
    return 0;
}


Java
// JAVA code to implement the above approach
import java.util.*;
class GFG {
  public static int
    countMinOp(int n, int m,
               ArrayList > mat)
  {
    // If all rows are operated,
    // there will be definitely an
    // answer.
    int ans = n;
 
    // Choose each column one by one.
    for (int i = 0; i < m - 1; i++) {
 
      // Calculate difference of
      // elements in i-th column
      // with final column.
      ArrayList diff
        = new ArrayList();
      for (int j = 0; j < n; j++) {
        diff.add(mat.get(j).get(i)
                 - mat.get(j).get(m - 1));
      }
 
      // Sort differences in
      // non-decreasing order.
      Collections.sort(diff,
                       Collections.reverseOrder());
 
      // Consider differences
      // until sum of differences is
      // non-negative, i.e.,
      // Sum[i] >= Sum[M].
      int sum = 0, k = 0;
 
      while ((k < n) && (sum + diff.get(k) >= 0)) {
        sum += diff.get(k);
        k++;
      }
 
      // Remaining elements must
      // be removed. Minimize the answer
      ans = Math.min(ans, n - k);
    }
    return ans;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int N = 3;
    int M = 3;
    ArrayList > mat
      = new ArrayList >();
    ArrayList temp1 = new ArrayList(
      Arrays.asList(3, 1, 2));
    ArrayList temp2 = new ArrayList(
      Arrays.asList(2, 3, 5));
    ArrayList temp3 = new ArrayList(
      Arrays.asList(3, 1, 2));
    mat.add(temp1);
    mat.add(temp2);
    mat.add(temp3);
    System.out.print(countMinOp(N, M, mat));
  }
}
 
// This code is contributed by Taranpreet


Python3
# Python 3 code to implement the above approach
def countMinOp(n, m, mat):
 
    # If all rows are operated,
    # there will be definitely an
    # answer.
    ans = n
 
    # Choose each column one by one.
    for i in range(m - 1):
 
        # Calculate difference of
        # elements in i-th column
        # with final column.
        diff = []
        for j in range(n):
            diff.append(mat[j][i]
                        - mat[j][m - 1])
 
        # Sort differences in
        # non-decreasing order.
        diff.sort(reverse = True)
 
        # Consider differences
        # until sum of differences is
        # non-negative, i.e.,
        # Sum[i] >= Sum[M].
        sum = 0
        k = 0
 
        while ((k < n) and (sum + diff[k]
                            >= 0)):
            sum += diff[k]
            k += 1
 
        # Remaining elements must
        # be removed. Minimize the answer
        ans = min(ans, n - k)
 
    return ans
 
# Driver Code
if __name__ == "__main__":
 
    N = 3
    M = 3
    mat = [[3, 1, 2], [2, 3, 5], [3, 1, 2]]
    print(countMinOp(N, M, mat))
 
    # This code is contributed by ukasp.


C#
// C# program of the above approach
using System;
using System.Linq;
using System.Collections.Generic;
 
class GFG
{
 
  static int
    countMinOp(int n, int m,
               List > mat)
  {
    // If all rows are operated,
    // there will be definitely an
    // answer.
    int ans = n;
 
    // Choose each column one by one.
    for (int i = 0; i < m - 1; i++) {
 
      // Calculate difference of
      // elements in i-th column
      // with final column.
      List diff
        = new List();
 
 
      diff.Add(-3);
      diff.Add(1);
      diff.Add(-1);
      diff.Add(-2);
      diff.Add(-1);
 
      // Sort differences in
      // non-decreasing order.
      diff.Sort();
      diff.Reverse();
 
      // Consider differences
      // until sum of differences is
      // non-negative, i.e.,
      // Sum[i] >= Sum[M].
      int sum = 0, k = 0;
 
      while ((k < n) && (sum + diff[k] >= 0)) {
        sum += diff[k];
        k++;
      }
 
      // Remaining elements must
      // be removed. Minimize the answer
      ans = Math.Min(ans, n - k);
    }
    return ans;
  }
 
  // Driver Code
  public static void Main()
  {
    int N = 3;
    int M = 3;
    List > mat
      = new List >();
    List temp1 = new List();
    temp1.Add(3);temp1.Add(1);temp1.Add(2);
    List temp2 = new List();
    temp2.Add(2);temp2.Add(3);temp2.Add(5);
    List temp3 = new List();
    temp3.Add(3);temp3.Add(1);temp3.Add(2);
    mat.Add(temp1);
    mat.Add(temp2);
    mat.Add(temp3);
    Console.Write(countMinOp(N, M, mat));
  }
}
 
// This code is contributed by sanjoy_62.


Javascript



输出
1

时间复杂度: O((2 N ) * N * M)
辅助空间 O(N * M)

有效方法:有效方法的基本思想是基于我们需要至少一列元素之和不小于最后一列的概念。因此,解决固定列的问题并重复每一列。请按照以下步骤解决问题:

  • 考虑两个数组,“A1”和“A2”,长度均为“N”,其中数组“A1”表示 1 到“M”-1 之间的任何列,数组“A2”表示第M列。
  • 我们从两个数组中删除一些索引,使得“A1”中剩余元素的总和不小于“A2”,即 Sum(A1) >= Sum(A2)。
    • 对于删除部分,最好删除所有索引中 ('A1[i]' – 'A2[i]') 更负的索引。
    • 如果 ('A1[i]' – 'A2[i]') 是非负数,我们根本不需要删除这个索引。
    • 取最负的一个,因为我们可能会也可能不会删除 ('A1[i]' – 'A2[i]') 为负数的索引。举个例子,如果 A1 = [3, 1, 4] 和 A2 = [2, 3, 2]。在这里,(A1[2] – A2[2]) 是负数,但我们不会删除它,因为其他元素正在处理总和。
  • 要以最佳方式执行上述任务:
    • 创建一个包含所有相应元素差异的数组“diff”,即“A1[i]”-“A2[i]”。
    • 按元素的降序对数组“diff”进行排序。
    • 取最长的前缀,直到前缀和为非负数,其余元素需要删除。
  • 对每一列重复上述过程,并考虑需要删除的最小元素数。

下面是上述方法的实现。

C++

// C++ code to implement the above approach
 
#include 
using namespace std;
 
int countMinOp(int n, int m,
               vector >& mat)
{
    // If all rows are operated,
    // there will be definitely an
    // answer.
    int ans = n;
 
    // Choose each column one by one.
    for (int i = 0; i < m - 1; i++) {
 
        // Calculate difference of
        // elements in i-th column
        // with final column.
        vector diff;
        for (int j = 0; j < n; j++) {
            diff.push_back(mat[j][i]
                           - mat[j][m - 1]);
        }
 
        // Sort differences in
        // non-decreasing order.
        sort(diff.begin(), diff.end(),
             greater());
     
 
        // Consider differences
        // until sum of differences is
        // non-negative, i.e.,
        // Sum[i] >= Sum[M].
        int sum = 0, k = 0;
 
        while ((k < n) and (sum + diff[k]
                            >= 0)) {
            sum += diff[k];
            k++;
        }
 
        // Remaining elements must
        // be removed. Minimize the answer
        ans = min(ans, n - k);
    }
    return ans;
}
 
// Driver Code
int main()
{
    int N = 3;
    int M = 3;
    vector > mat
        = { { 3, 1, 2 }, { 2, 3, 5 }, { 3, 1, 2 } };
    cout << countMinOp(N, M, mat);
    return 0;
}

Java

// JAVA code to implement the above approach
import java.util.*;
class GFG {
  public static int
    countMinOp(int n, int m,
               ArrayList > mat)
  {
    // If all rows are operated,
    // there will be definitely an
    // answer.
    int ans = n;
 
    // Choose each column one by one.
    for (int i = 0; i < m - 1; i++) {
 
      // Calculate difference of
      // elements in i-th column
      // with final column.
      ArrayList diff
        = new ArrayList();
      for (int j = 0; j < n; j++) {
        diff.add(mat.get(j).get(i)
                 - mat.get(j).get(m - 1));
      }
 
      // Sort differences in
      // non-decreasing order.
      Collections.sort(diff,
                       Collections.reverseOrder());
 
      // Consider differences
      // until sum of differences is
      // non-negative, i.e.,
      // Sum[i] >= Sum[M].
      int sum = 0, k = 0;
 
      while ((k < n) && (sum + diff.get(k) >= 0)) {
        sum += diff.get(k);
        k++;
      }
 
      // Remaining elements must
      // be removed. Minimize the answer
      ans = Math.min(ans, n - k);
    }
    return ans;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int N = 3;
    int M = 3;
    ArrayList > mat
      = new ArrayList >();
    ArrayList temp1 = new ArrayList(
      Arrays.asList(3, 1, 2));
    ArrayList temp2 = new ArrayList(
      Arrays.asList(2, 3, 5));
    ArrayList temp3 = new ArrayList(
      Arrays.asList(3, 1, 2));
    mat.add(temp1);
    mat.add(temp2);
    mat.add(temp3);
    System.out.print(countMinOp(N, M, mat));
  }
}
 
// This code is contributed by Taranpreet

Python3

# Python 3 code to implement the above approach
def countMinOp(n, m, mat):
 
    # If all rows are operated,
    # there will be definitely an
    # answer.
    ans = n
 
    # Choose each column one by one.
    for i in range(m - 1):
 
        # Calculate difference of
        # elements in i-th column
        # with final column.
        diff = []
        for j in range(n):
            diff.append(mat[j][i]
                        - mat[j][m - 1])
 
        # Sort differences in
        # non-decreasing order.
        diff.sort(reverse = True)
 
        # Consider differences
        # until sum of differences is
        # non-negative, i.e.,
        # Sum[i] >= Sum[M].
        sum = 0
        k = 0
 
        while ((k < n) and (sum + diff[k]
                            >= 0)):
            sum += diff[k]
            k += 1
 
        # Remaining elements must
        # be removed. Minimize the answer
        ans = min(ans, n - k)
 
    return ans
 
# Driver Code
if __name__ == "__main__":
 
    N = 3
    M = 3
    mat = [[3, 1, 2], [2, 3, 5], [3, 1, 2]]
    print(countMinOp(N, M, mat))
 
    # This code is contributed by ukasp.

C#

// C# program of the above approach
using System;
using System.Linq;
using System.Collections.Generic;
 
class GFG
{
 
  static int
    countMinOp(int n, int m,
               List > mat)
  {
    // If all rows are operated,
    // there will be definitely an
    // answer.
    int ans = n;
 
    // Choose each column one by one.
    for (int i = 0; i < m - 1; i++) {
 
      // Calculate difference of
      // elements in i-th column
      // with final column.
      List diff
        = new List();
 
 
      diff.Add(-3);
      diff.Add(1);
      diff.Add(-1);
      diff.Add(-2);
      diff.Add(-1);
 
      // Sort differences in
      // non-decreasing order.
      diff.Sort();
      diff.Reverse();
 
      // Consider differences
      // until sum of differences is
      // non-negative, i.e.,
      // Sum[i] >= Sum[M].
      int sum = 0, k = 0;
 
      while ((k < n) && (sum + diff[k] >= 0)) {
        sum += diff[k];
        k++;
      }
 
      // Remaining elements must
      // be removed. Minimize the answer
      ans = Math.Min(ans, n - k);
    }
    return ans;
  }
 
  // Driver Code
  public static void Main()
  {
    int N = 3;
    int M = 3;
    List > mat
      = new List >();
    List temp1 = new List();
    temp1.Add(3);temp1.Add(1);temp1.Add(2);
    List temp2 = new List();
    temp2.Add(2);temp2.Add(3);temp2.Add(5);
    List temp3 = new List();
    temp3.Add(3);temp3.Add(1);temp3.Add(2);
    mat.Add(temp1);
    mat.Add(temp2);
    mat.Add(temp3);
    Console.Write(countMinOp(N, M, mat));
  }
}
 
// This code is contributed by sanjoy_62.

Javascript



输出
1

时间复杂度: O(N * M * logN)
辅助空间 O(N)