Open In App
Related Articles

Allocate Minimum Number of Pages from N books to M students

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Report issue
Report

Given that there are N books and M students. Also given are the number of pages in each book in ascending order. The task is to assign books in such a way that the maximum number of pages assigned to a student is minimum, with the condition that every student is assigned to read some consecutive books. Print that minimum number of pages.

Example : 

Input: N = 4, pages[] = {12, 34, 67, 90}, M = 2

Output: 113

Explanation: There are 2 number of students. Books can be distributed in following combinations: 

  1. [12] and [34, 67, 90] -> Max number of pages is allocated to student ‘2’ with 34 + 67 + 90 = 191 pages
  2. [12, 34] and [67, 90] -> Max number of pages is allocated to student ‘2’ with 67 + 90 = 157 pages 
  3. [12, 34, 67] and [90] -> Max number of pages is allocated to student ‘1’ with 12 + 34 + 67 = 113 pages

Of the 3 cases, Option 3 has the minimum pages = 113.

Naive Approach: The simplest approach to solve this problem is to find all permutations to distribute N books among M students, and return the minimum page allocation among them.

Efficient Approach: 

Another way to solve this problem is to use Binary Search, based on this idea:

Case 1: When no valid answer exists.

  • If the number of students is greater than the number of books (i.e, M > N), In this case at least 1 student will be left to which no book has been assigned.

Case 2: When a valid answer exists.

  • The maximum possible answer could be when there is only one student. So, all the book will be assigned to him and the result would be the sum of pages of all the books.
  • The minimum possible answer could be when number of student is equal to the number of book (i.e, M == N) , In this case all the students will get at most one book. So, the result would be the maximum number of pages among them (i.e, maximum(pages[])).
  • Hence, we can apply binary search in this given range and each time we can consider the mid value as the maximum limit of pages one can get. And check for the limit if answer is valid then update the limit accordingly.

Below is the approach to solve this problem using Binary Search:

  • Calculate the mid and check if mid number of pages can be assigned to students such that all students will get at least one book.
  • If yes, then update the result and check for the previous search space (end = mid-1)
  • Otherwise, check for the next search space (start = mid+1)

Below is the implementation of the above approach:

C++

// C++ program for optimal allocation of pages
#include <bits/stdc++.h>
using namespace std;
 
// Utility function to check if current minimum value
// is feasible or not.
bool isPossible(int arr[], int n, int m, int curr_min)
{
    int studentsRequired = 1;
    int curr_sum = 0;
 
    // iterate over all books
    for (int i = 0; i < n; i++) {
        // check if current number of pages are greater
        // than curr_min that means we will get the result
        // after mid no. of pages
        if (arr[i] > curr_min)
            return false;
 
        // count how many students are required
        // to distribute curr_min pages
        if (curr_sum + arr[i] > curr_min) {
            // increment student count
            studentsRequired++;
 
            // update curr_sum
            curr_sum = arr[i];
 
            // if students required becomes greater
            // than given no. of students,return false
            if (studentsRequired > m)
                return false;
        }
 
        // else update curr_sum
        else
            curr_sum += arr[i];
    }
    return true;
}
 
// function to find minimum pages
int findPages(int arr[], int n, int m)
{
    long long sum = 0;
 
    // return -1 if no. of books is less than
    // no. of students
    if (n < m)
        return -1;
    int mx = INT_MIN;
 
    // Count total number of pages
    for (int i = 0; i < n; i++) {
        sum += arr[i];
        mx = max(mx, arr[i]);
    }
 
    // initialize start as 0 pages and end as
    // total pages
    int start = mx, end = sum;
    int result = INT_MAX;
 
    // traverse until start <= end
    while (start <= end) {
        // check if it is possible to distribute
        // books by using mid as current minimum
        int mid = (start + end) / 2;
        if (isPossible(arr, n, m, mid)) {
            // update result to current distribution
            // as it's the best we have found till now.
            result = mid;
 
            // as we are finding minimum and books
            // are sorted so reduce end = mid -1
            // that means
            end = mid - 1;
        }
 
        else
            // if not possible means pages should be
            // increased so update start = mid + 1
            start = mid + 1;
    }
 
    // at-last return minimum no. of  pages
    return result;
}
 
// Drivers code
int main()
{
    // Number of pages in books
    int arr[] = { 12, 34, 67, 90 };
    int n = sizeof arr / sizeof arr[0];
    int m = 2; // No. of students
 
    cout << "Minimum number of pages = "
         << findPages(arr, n, m) << endl;
    return 0;
}
 
// This code is contributed by Aditya Kumar (adityakumar129)

                    

C

// C program for optimal allocation of pages
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
 
// Utility function to check if current minimum value
// is feasible or not.
bool isPossible(int arr[], int n, int m, int curr_min)
{
    int studentsRequired = 1;
    int curr_sum = 0;
 
    // iterate over all books
    for (int i = 0; i < n; i++) {
        // check if current number of pages are greater
        // than curr_min that means we will get the result
        // after mid no. of pages
        if (arr[i] > curr_min)
            return false;
 
        // count how many students are required
        // to distribute curr_min pages
        if (curr_sum + arr[i] > curr_min) {
            // increment student count
            studentsRequired++;
 
            // update curr_sum
            curr_sum = arr[i];
 
            // if students required becomes greater
            // than given no. of students,return false
            if (studentsRequired > m)
                return false;
        }
 
        // else update curr_sum
        else
            curr_sum += arr[i];
    }
    return true;
}
 
// function to find minimum pages
int findPages(int arr[], int n, int m)
{
    long long sum = 0;
 
    // return -1 if no. of books is less than
    // no. of students
    if (n < m)
        return -1;
    int mx = arr[0];
 
    // Count total number of pages
    for (int i = 0; i < n; i++) {
        sum += arr[i];
        mx = (arr[i] > mx ? arr[i] : mx);
    }
 
    // initialize start as 0 pages and end as
    // total pages
    int start = mx, end = sum;
    int result = INT_MAX;
 
    // traverse until start <= end
    while (start <= end) {
        // check if it is possible to distribute
        // books by using mid as current minimum
        int mid = (start + end) / 2;
        if (isPossible(arr, n, m, mid)) {
            // update result to current distribution
            // as it's the best we have found till now.
            result = mid;
 
            // as we are finding minimum and books
            // are sorted so reduce end = mid -1
            // that means
            end = mid - 1;
        }
 
        else
            // if not possible means pages should be
            // increased so update start = mid + 1
            start = mid + 1;
    }
 
    // at-last return minimum no. of  pages
    return result;
}
 
// Drivers code
int main()
{
    // Number of pages in books
    int arr[] = { 12, 34, 67, 90 };
    int n = sizeof arr / sizeof arr[0];
    int m = 2; // No. of students
 
    printf("Minimum number of pages = %d\n",
           findPages(arr, n, m));
    return 0;
}
 
// This code is contributed by Aditya Kumar (adityakumar129)

                    

Java

// Java program for optimal allocation of pages
 
public class GFG {
    // Utility method to check if current minimum value
    // is feasible or not.
    static boolean isPossible(int arr[], int n, int m,
                              int curr_min)
    {
        int studentsRequired = 1;
        int curr_sum = 0;
 
        // iterate over all books
        for (int i = 0; i < n; i++) {
            curr_sum += arr[i];
            if (curr_sum > curr_min) {
                studentsRequired++; // increment student
                                    // count
 
                curr_sum = arr[i]; // update curr_sum
            }
        }
 
        return studentsRequired <= m;
    }
 
    // method to find minimum pages
    static int findPages(int arr[], int n, int m)
    {
        int sum = 0;
 
        // return -1 if no. of books is less than
        // no. of students
        if (n < m)
            return -1;
        int mx = arr[0];
 
        // Count total number of pages
        for (int i = 0; i < n; i++) {
            sum += arr[i];
            mx = (arr[i] > mx ? arr[i] : mx);
        }
 
        // initialize start as arr[n-1] pages(minimum answer
        // possible) and end as total pages(maximum answer
        // possible)
        int start = arr[n - 1], end = sum;
        int result = Integer.MAX_VALUE;
 
        // traverse until start <= end
        while (start <= end) {
            // check if it is possible to distribute
            // books by using mid is current minimum
            int mid = start + (end - start) / 2;
            if (isPossible(arr, n, m, mid)) {
                // update result to current distribution
                // as it's the best we have found till now.
                result = mid;
 
                // as we are finding minimum so,
                end = mid - 1;
            }
 
            else
                // if not possible, means pages should be
                // increased ,so update start = mid + 1
                start = mid + 1;
        }
 
        // at-last return minimum no. of  pages
        return result;
    }
 
    // Driver Method
    public static void main(String[] args)
    {
 
        int arr[] = { 12, 34, 67,
                      90 }; // Number of pages in books
 
        int m = 2; // No. of students
 
        System.out.println("Minimum number of pages = "
                           + findPages(arr, arr.length, m));
    }
}
 
// This code is contributed by Aditya Kumar (adityakumar129)

                    

Python3

# Python3 program for optimal allocation of pages
 
# Utility function to check if
# current minimum value is feasible or not.
 
 
def isPossible(arr, n, m, curr_min):
    studentsRequired = 1
    curr_sum = 0
 
    # iterate over all books
    for i in range(n):
 
        # check if current number of pages are
        # greater than curr_min that means
        # we will get the result after
        # mid no. of pages
        if (arr[i] > curr_min):
            return False
 
        # count how many students are required
        # to distribute curr_min pages
        if (curr_sum + arr[i] > curr_min):
 
            # increment student count
            studentsRequired += 1
 
            # update curr_sum
            curr_sum = arr[i]
 
            # if students required becomes greater
            # than given no. of students, return False
            if (studentsRequired > m):
                return False
 
        # else update curr_sum
        else:
            curr_sum += arr[i]
 
    return True
 
# function to find minimum pages
 
 
def findPages(arr, n, m):
 
    sum = 0
 
    # return -1 if no. of books is
    # less than no. of students
    if (n < m):
        return -1
 
    # Count total number of pages
    for i in range(n):
        sum += arr[i]
 
    # initialize start as 0 pages and
    # end as total pages
    start, end = 0, sum
    result = 10**9
 
    # traverse until start <= end
    while (start <= end):
 
        # check if it is possible to distribute
        # books by using mid as current minimum
        mid = (start + end) // 2
        if (isPossible(arr, n, m, mid)):
 
            # update result to current distribution
              # as it's the best we have found till now.
            result = mid
 
            # as we are finding minimum and books
            # are sorted so reduce end = mid -1
            # that means
            end = mid - 1
 
        else:
            # if not possible means pages should be
            # increased so update start = mid + 1
            start = mid + 1
 
    # at-last return minimum no. of pages
    return result
 
# Driver Code
 
 
# Number of pages in books
arr = [12, 34, 67, 90]
n = len(arr)
m = 2   # No. of students
 
print("Minimum number of pages = ",
      findPages(arr, n, m))
 
# This code is contributed by Mohit Kumar

                    

C#

// C# program for optimal
// allocation of pages
using System;
 
class GFG {
 
    // Utility function to check
    // if current minimum value
    // is feasible or not.
    static bool isPossible(int[] arr, int n, int m,
                           int curr_min)
    {
        int studentsRequired = 1;
        int curr_sum = 0;
 
        // iterate over all books
        for (int i = 0; i < n; i++) {
            // check if current number of
            // pages are greater than curr_min
            // that means we will get the
            // result after mid no. of pages
            if (arr[i] > curr_min)
                return false;
 
            // count how many students
            // are required to distribute
            // curr_min pages
            if (curr_sum + arr[i] > curr_min) {
                // increment student count
                studentsRequired++;
 
                // update curr_sum
                curr_sum = arr[i];
 
                // if students required becomes
                // greater than given no. of
                // students, return false
                if (studentsRequired > m)
                    return false;
            }
 
            // else update curr_sum
            else
                curr_sum += arr[i];
        }
        return true;
    }
 
    // function to find minimum pages
    static int findPages(int[] arr, int n, int m)
    {
        long sum = 0;
 
        // return -1 if no. of books
        // is less than no. of students
        if (n < m)
            return -1;
        int mx = arr[0];
        // Count total number of pages
        for (int i = 0; i < n; i++) {
            sum += arr[i];
 
            mx = (arr[i] > mx ? arr[i] : mx);
        }
 
        // initialize start as 0 pages
        // and end as total pages
        int start = 0, end = (int)sum;
        int result = int.MaxValue;
 
        // traverse until start <= end
        while (start <= end) {
            // check if it is possible to
            // distribute books by using
            // mid as current minimum
            int mid = (start + end) / 2;
            if (isPossible(arr, n, m, mid)) {
                // update result to current distribution
                // as it's the best we have found till now.
                result = mid;
 
                // as we are finding minimum and
                // books are sorted so reduce
                // end = mid -1 that means
                end = mid - 1;
            }
 
            else
                // if not possible means pages
                // should be increased so update
                // start = mid + 1
                start = mid + 1;
        }
 
        // at-last return
        // minimum no. of pages
        return result;
    }
 
    // Drivers code
    static public void Main()
    {
 
        // Number of pages in books
        int[] arr = { 12, 34, 67, 90 };
        int n = arr.Length;
        int m = 2; // No. of students
 
        Console.WriteLine("Minimum number of pages = "
                          + findPages(arr, n, m));
    }
}
 
// This code is contributed by anuj_67.

                    

PHP

<?php
// PHP program for optimal allocation
// of pages
 
// Utility function to check if current
// minimum value is feasible or not.
 
function isPossible($arr, $n, $m,
                    $curr_min)
{
    $studentsRequired = 1;
    $curr_sum = 0;
 
    // iterate over all books
    for ( $i = 0; $i < $n; $i++)
    {
        // check if current number of pages
        // are greater than curr_min that
        // means we will get the result
        // after mid no. of pages
        if ($arr[$i] > $curr_min)
            return false;
 
        // count how many students are
        // required to distribute
        // curr_min pages
        if ($curr_sum + $arr[$i] > $curr_min)
        {
            // increment student count
            $studentsRequired++;
 
            // update curr_sum
            $curr_sum = $arr[$i];
 
            // if students required becomes
            // greater than given no. of
            // students, return false
            if ($studentsRequired > $m)
                return false;
        }
 
        // else update curr_sum
        else
            $curr_sum += $arr[$i];
    }
    return true;
}
 
// function to find minimum pages
function findPages($arr, $n, $m)
{
    $sum = 0;
 
    // return -1 if no. of books is
    // less than no. of students
    if ($n < $m)
        return -1;
 
    // Count total number of pages
    for ($i = 0; $i < $n; $i++)
        $sum += $arr[$i];
 
    // initialize start as 0 pages
    // and end as total pages
    $start = 0;
    $end = $sum;
    $result = PHP_INT_MAX;
 
    // traverse until start <= end
    while ($start <= $end)
    {
        // check if it is possible to
        // distribute books by using
        // mid as current minimum
        $mid = (int)($start + $end) / 2;
        if (isPossible($arr, $n, $m, $mid))
        {
            // update result to current distribution
              // as it's the best we have found till now
            $result = $mid;
 
            // as we are finding minimum and
            // books are sorted so reduce
            // end = mid -1 that means
            $end = $mid - 1;
        }
 
        else
            // if not possible means pages
            // should be increased so update
            // start = mid + 1
            $start = $mid + 1;
    }
 
    // at-last return minimum
    // no. of pages
    return $result;
}
 
// Driver code
 
// Number of pages in books
$arr = array(12, 34, 67, 90);
$n = count($arr);
$m = 2; // No. of students
 
echo "Minimum number of pages = ",
    findPages($arr, $n, $m), "\n";
 
// This code is contributed by Sach_Code
?>

                    

Javascript

// Javascript program for optimal allocation of pages
 
 
// Utility method to check if current minimum value
// is feasible or not.
function isPossible(arr,n,m,curr_min)
{
    let studentsRequired = 1;
    let curr_sum = 0;
     
   
    // iterate over all books
    for (let i = 0; i < n; i++)
    {
        // check if current number of pages are greater
        // than curr_min that means we will get the result
        // after mid no. of pages
        if (arr[i] > curr_min)
            return false;
   
        // count how many students are required
        // to distribute curr_min pages
        if (curr_sum + arr[i] > curr_min)
        {
            // increment student count
            studentsRequired++;
   
            // update curr_sum
            curr_sum = arr[i];
   
            // if students required becomes greater
            // than given no. of students,return false
            if (studentsRequired > m)
                return false;
        }
   
        // else update curr_sum
        else
            curr_sum += arr[i];
    }
    return true;
}
 
// method to find minimum pages
function findPages(arr,n,m)
{
    let sum = 0;
    int mx = arr[0] ;
   
    // return -1 if no. of books is less than
    // no. of students
    if (n < m)
        return -1;
   
    // Count total number of pages
    for (let i = 0; i < n; i++){
     sum += arr[i];
     mx = (arr[i] > mx ? arr[i] : mx) ;
    }
        
   
    // initialize start as 0 pages and end as
    // total pages
    let start = 0, end = sum;
    let result = Number.MAX_VALUE;
   
    // traverse until start <= end
    while (start <= end)
    {
        // check if it is possible to distribute
        // books by using mid as current minimum
        let mid =Math.floor( (start + end) / 2);
        if (isPossible(arr, n, m, mid))
        {
            // if yes then find the minimum distribution
            result = Math.min(result, mid);
   
            // as we are finding minimum and books
            // are sorted so reduce end = mid -1
            // that means
            end = mid - 1;
        }
   
        else
            // if not possible means pages should be
            // increased so update start = mid + 1
            start = mid + 1;
    }
   
    // at-last return minimum no. of  pages
    return result;
}
 
// Driver Method
let arr=[12, 34, 67, 90];
let m = 2; //No. of students
console.log("Minimum number of pages = " +
                          findPages(arr, arr.length, m));
 
 
 
// This code is contributed by patel2127

                    

Output
Minimum number of pages = 113

Time Complexity: O(N*log(N)), Where N is the total number of pages in the book.

Auxiliary Space: O(1)



Last Updated : 09 Jun, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads