📜  根据给定的规则,最小化 K 让人 A 消耗至少 ceil(N/(M + 1)) 个糖果

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

根据给定的规则,最小化 K 让人 A 消耗至少 ceil(N/(M + 1)) 个糖果

给定N个糖果, M个人,以及一个由M个正整数组成的数组arr[] ,任务是找到K的最小值,使得一个人 A能够消耗至少 ceil 的总数(N/(M + 1))糖果按照以下规则:

  • 在第一回合中, A 人消耗了剩下的糖果数量K中的最小值。
  • 在接下来的M轮中,范围为 [0, M-1]的每个第 i个人消耗了arr[i]百分比的剩余糖果。
  • 重复上述步骤,直到没有糖果。

例子:

朴素方法:解决给定问题的最简单方法是检查每个人 A将获得的糖果数量是否为K的所有可能值。请按照以下步骤解决此问题:

  • 找到(N/(M + 1))的值并将其存储在一个变量中,说,因为这是A想吃的最少糖果。
  • 遍历[1, N]范围内的所有K值并执行以下步骤:
    • 对于每个K值,模拟上面提到的过程并计算人 A将获得的糖果总数。
    • 如果糖果的数量至少是good的值,则跳出循环。否则,继续迭代。
  • 完成上述步骤后,打印出K的当前值作为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
void minimumK(vector &arr, int M,
              int N)
{
    // Find the minimum required value
      // of candies for the first person
    int good = ceil((N * 1.0)
                    / ((M + 1) * 1.0));
 
 
    // Iterate K from [1, n]
    for (int i = 1; i <= N; i++) {
 
          int K = i;
 
          // Total number of candies
        int candies = N;
       
          // Candies taken by Person 1
          int taken = 0;
       
        while (candies > 0) {
           
            // Candies taken by 1st
            // person is minimum of K
            // and candies left         
            taken += min(K, candies);
            candies -= min(K, candies);
 
            // Traverse the array arr[]         
            for (int j = 0; j < M; j++) {
               
                // Amount consumed by the
                  // person j
                int consume = (arr[j]
                               * candies) / 100;
                 
                // Update the number
                  // of candies
                candies -= consume;
            }
        }
 
        // Good share of candies achieved
        if (taken >= good) {
            cout << i;
            return;
        }
    }
}
 
// Driver Code
int main()
{
    int N = 13, M = 1;
    vector arr = { 50 }; 
    minimumK(arr, M, N);
   
      return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
static void minimumK(ArrayList arr, int M,
                                             int N)
{
     
    // Find the minimum required value
    // of candies for the first person
    int good = (int)((N * 1.0) / ((M + 1) * 1.0)) + 1;
 
    // Iterate K from [1, n]
    for(int i = 1; i <= N; i++)
    {
        int K = i;
 
        // Total number of candies
        int candies = N;
 
        // Candies taken by Person 1
        int taken = 0;
 
        while (candies > 0)
        {
             
            // Candies taken by 1st
            // person is minimum of K
            // and candies left
            taken += Math.min(K, candies);
            candies -= Math.min(K, candies);
 
            // Traverse the array arr[]
            for(int j = 0; j < M; j++)
            {
                 
                // Amount consumed by the
                // person j
                int consume = (arr.get(j) * candies) / 100;
 
                // Update the number
                // of candies
                candies -= consume;
            }
        }
 
        // Good share of candies achieved
        if (taken >= good)
        {
            System.out.print(i);
            return;
        }
    }
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 13, M = 1;
    ArrayList arr = new ArrayList();
    arr.add(50);
     
    minimumK(arr, M, N);
}
}
 
// This code is contributed by subhammahato348


Python3
# Python 3 program for the above approach
import math
# Function to find minimum value of
# K such that the first person gets
# at least (N/(M+1)) candies
def minimumK(arr,  M, N):
 
    # Find the minimum required value
    # of candies for the first person
    good = math.ceil((N * 1.0) / ((M + 1) * 1.0))
 
    # Iterate K from [1, n]
    for i in range(1, N + 1):
        K = i
 
        # Total number of candies
        candies = N
 
        # Candies taken by Person 1
        taken = 0
 
        while (candies > 0):
 
            # Candies taken by 1st
            # person is minimum of K
            # and candies left
            taken += min(K, candies)
            candies -= min(K, candies)
 
            # Traverse the array arr[]
            for j in range(M):
 
                # Amount consumed by the
                # person j
                consume = (arr[j]
                           * candies) / 100
 
                # Update the number
                # of candies
                candies -= consume
                         
        # Good share of candies achieved
        if (taken >= good):
          print(i)
          return
 
# Driver Code
if __name__ == "__main__":
 
    N = 13
    M = 1
    arr = [50]
    minimumK(arr, M, N)
 
    # This code is contributed by ukasp.


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
static void minimumK(List arr, int M,
              int N)
{
    // Find the minimum required value
      // of candies for the first person
    int good = (int)((N * 1.0) / ((M + 1) * 1.0))+1;
 
    // Iterate K from [1, n]
    for (int i = 1; i <= N; i++) {
 
          int K = i;
 
          // Total number of candies
          int candies = N;
       
          // Candies taken by Person 1
          int taken = 0;
       
        while (candies > 0) {
           
            // Candies taken by 1st
            // person is minimum of K
            // and candies left         
            taken += Math.Min(K, candies);
            candies -= Math.Min(K, candies);
 
            // Traverse the array arr[]         
            for (int j = 0; j < M; j++) {
               
                // Amount consumed by the
                  // person j
                int consume = (arr[j]
                               * candies) / 100;
                 
                // Update the number
                  // of candies
                candies -= consume;
            }
        }
 
        // Good share of candies achieved
        if (taken >= good) {
            Console.Write(i);
            return;
        }
    }
}
 
// Driver Code
public static void Main()
{
    int N = 13, M = 1;
    List arr = new List();
    arr.Add(50); 
    minimumK(arr, M, N);
}
}
 
// This code is contributed by SURENDRA_GANGWAR.


Javascript


C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to check if the value of
// mid gives at least (N/(M + 1))
// candies or not
bool check(int K, int n, int m,
           vector arr,
           int good_share)
{
    int candies = n, taken = 0;
 
    while (candies > 0) {
 
        // Candies taken by 1st
        // person is minimum of K
        // and candies left
        taken += min(K, candies);
        candies -= min(K, candies);
 
        // Traverse the given array
        for (int j = 0; j < m; j++) {
 
            // Amount consumed by
              // person j
            int consume = (arr[j] * candies) / 100;
 
            // Update the count of
              // candies
            candies -= consume;
        }
    }
 
    // Check if person 1 gets the
      // good share of candies
    return (taken >= good_share);
}
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
void minimumK(vector &arr, int N,
              int M)
{
    // Find the minimum required value
      // of candies for the first person
    int good_share = ceil((N * 1.0)
                          / ((M + 1) * 1.0));
 
    int lo = 1, hi = N;
 
      // Iterate until low is less
      // than or equal to mid
    while (lo < hi) {
 
        // Find the value of mid
        int mid = (lo + hi) / 2;
 
        // Check for mid, whether it
          // can be the possible value
          // of K or not
        if (check(mid, N, M, arr,
                  good_share)) {
 
            // Update the value of hi
            hi = mid;
        }
       
          // Otherwise, update the
          // value of lo
        else {
            lo = mid + 1;
        }
    }
 
    // Print the resultant minimum
      // value of K
    cout << hi;
}
 
// Driver Code
int main()
{
    int N = 13, M = 1;
    vector arr = { 50 };
   
    minimumK(arr, N, M);
   
      return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG {
 
// Function to check if the value of
// mid gives at least (N/(M + 1))
// candies or not
static boolean check(int K, int n, int m,
           ArrayList arr,
           int good_share)
{
    int candies = n, taken = 0;
 
    while (candies > 0) {
 
        // Candies taken by 1st
        // person is minimum of K
        // and candies left
        taken += Math.min(K, candies);
        candies -= Math.min(K, candies);
 
        // Traverse the given array
        for (int j = 0; j < m; j++) {
 
            // Amount consumed by
              // person j
            int consume = (arr.get(j) * candies) / 100;
 
            // Update the count of
              // candies
            candies -= consume;
        }
    }
 
    // Check if person 1 gets the
      // good share of candies
    return (taken >= good_share);
}
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
static void minimumK(ArrayList arr, int N,
              int M)
{
    // Find the minimum required value
      // of candies for the first person
    int good_share = (int)Math.ceil((N * 1.0)
                          / ((M + 1) * 1.0));
 
    int lo = 1, hi = N;
 
      // Iterate until low is less
      // than or equal to mid
    while (lo < hi) {
 
        // Find the value of mid
        int mid = (lo + hi) / 2;
 
        // Check for mid, whether it
          // can be the possible value
          // of K or not
        if (check(mid, N, M, arr,
                  good_share)) {
 
            // Update the value of hi
            hi = mid;
        }
       
          // Otherwise, update the
          // value of lo
        else {
            lo = mid + 1;
        }
    }
 
    // Print the resultant minimum
      // value of K
    System.out.print(hi);
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 13, M = 1;
    ArrayList arr = new ArrayList();
    arr.add(50);
   
    minimumK(arr, N, M);
}
}
 
// This code is contributed by avijitmondal1998.


输出:

3

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

高效方法:上述方法也可以通过使用二分搜索进行优化。请按照以下步骤解决问题:

  • 找到(N/(M + 1))的值并将其存储在一个变量中,说,因为这是A想吃的最少糖果。
  • 初始化两个变量,比如分别为1N。
  • 迭代直到low小于high并执行以下步骤:
    • 找到mid的值为(low + high)/2
    • 通过模拟上面提到的过程,找到人 AK值为mid的最小糖果数量。
    • 如果人 A拿走的糖果数量至少不错,则将high的值更新为mid 。否则,将low的值更新为(mid + 1)
  • 完成上述步骤后,将high的值打印为K的结果最小值。

下面是上述方法的实现:

C++

// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to check if the value of
// mid gives at least (N/(M + 1))
// candies or not
bool check(int K, int n, int m,
           vector arr,
           int good_share)
{
    int candies = n, taken = 0;
 
    while (candies > 0) {
 
        // Candies taken by 1st
        // person is minimum of K
        // and candies left
        taken += min(K, candies);
        candies -= min(K, candies);
 
        // Traverse the given array
        for (int j = 0; j < m; j++) {
 
            // Amount consumed by
              // person j
            int consume = (arr[j] * candies) / 100;
 
            // Update the count of
              // candies
            candies -= consume;
        }
    }
 
    // Check if person 1 gets the
      // good share of candies
    return (taken >= good_share);
}
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
void minimumK(vector &arr, int N,
              int M)
{
    // Find the minimum required value
      // of candies for the first person
    int good_share = ceil((N * 1.0)
                          / ((M + 1) * 1.0));
 
    int lo = 1, hi = N;
 
      // Iterate until low is less
      // than or equal to mid
    while (lo < hi) {
 
        // Find the value of mid
        int mid = (lo + hi) / 2;
 
        // Check for mid, whether it
          // can be the possible value
          // of K or not
        if (check(mid, N, M, arr,
                  good_share)) {
 
            // Update the value of hi
            hi = mid;
        }
       
          // Otherwise, update the
          // value of lo
        else {
            lo = mid + 1;
        }
    }
 
    // Print the resultant minimum
      // value of K
    cout << hi;
}
 
// Driver Code
int main()
{
    int N = 13, M = 1;
    vector arr = { 50 };
   
    minimumK(arr, N, M);
   
      return 0;
}

Java

// Java program for the above approach
import java.util.*;
 
class GFG {
 
// Function to check if the value of
// mid gives at least (N/(M + 1))
// candies or not
static boolean check(int K, int n, int m,
           ArrayList arr,
           int good_share)
{
    int candies = n, taken = 0;
 
    while (candies > 0) {
 
        // Candies taken by 1st
        // person is minimum of K
        // and candies left
        taken += Math.min(K, candies);
        candies -= Math.min(K, candies);
 
        // Traverse the given array
        for (int j = 0; j < m; j++) {
 
            // Amount consumed by
              // person j
            int consume = (arr.get(j) * candies) / 100;
 
            // Update the count of
              // candies
            candies -= consume;
        }
    }
 
    // Check if person 1 gets the
      // good share of candies
    return (taken >= good_share);
}
 
// Function to find minimum value of
// K such that the first person gets
// at least (N/(M+1)) candies
static void minimumK(ArrayList arr, int N,
              int M)
{
    // Find the minimum required value
      // of candies for the first person
    int good_share = (int)Math.ceil((N * 1.0)
                          / ((M + 1) * 1.0));
 
    int lo = 1, hi = N;
 
      // Iterate until low is less
      // than or equal to mid
    while (lo < hi) {
 
        // Find the value of mid
        int mid = (lo + hi) / 2;
 
        // Check for mid, whether it
          // can be the possible value
          // of K or not
        if (check(mid, N, M, arr,
                  good_share)) {
 
            // Update the value of hi
            hi = mid;
        }
       
          // Otherwise, update the
          // value of lo
        else {
            lo = mid + 1;
        }
    }
 
    // Print the resultant minimum
      // value of K
    System.out.print(hi);
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 13, M = 1;
    ArrayList arr = new ArrayList();
    arr.add(50);
   
    minimumK(arr, N, M);
}
}
 
// This code is contributed by avijitmondal1998.

时间复杂度: O(N * log N)
辅助空间: O(1)