Given are N boards of with length of each given in the form of array, and K painters, such that each painter takes 1 unit of time to paint 1 unit of the board. The task is to find the minimum time to paint all boards under the constraints that any painter will only paint continuous sections of boards, say board {2, 3, 4} or only board {1} or nothing but not board {2, 4, 5}.
Examples:
Input: N = 4, A = {10, 10, 10, 10}, K = 2
Output : 20
Explanation: Here we can divide the boards into 2 equal sized partitions (Painter 1 will paint boards A1 and A2, and Painter 2 will paint boards A3 and A4). So each painter gets 20 units of board and the total time taken is 20.
Input: N = 4, A = {10, 20, 30, 40}, K = 2
Output : 60
Explanation: Since there are only 2 painters, therefore divide first 3 boards to painter 1 (A1, A2 and A3) with time = 60, and last board to painter 2 (A4) with time = 40. Therefore total time taken = 60, which is the minimum possible.
Please note the combination A1 and A4 to Painter 1 with time 50, and A2 and A3 to Painter 2 with time 50, will yield a smaller time (50 units). But this cant be considered due to the constraint that a painter cannot paint non-continuos series of boards.
In the Painter’s Programming, we have discussed a dynamic programming based approach having time complexity of O(k∗N2) and O(k∗N) extra space. In this post we will look into a more efficient approach using binary search.
Efficient Approach for Painter’s Problem using Binary Search
The idea to apply Binary Search Approach to Painter’s Problem is based on following observations:
We know that the invariant of binary search has three main parts:
- the target value would always be in the searching range.
- the searching range will decrease in each loop so that the termination can be reached.
- We also know that the values in this range must be in sorted order.
Here our target value is the maximum sum of a contiguous section in the optimal allocation of boards.
Now how can we apply binary search for this?
We can fix the possible low to high range for the target value and narrow down our search to get the optimal allocation.
- We can see that the highest possible value in this range is the sum of all the elements in the array and this happens when we allot 1 painter all the sections of the board.
- The lowest possible value of this range is the maximum value of the array max, as in this allocation we can allot max to one painter and divide the other sections such that the cost of them is less than or equal to max and as close as possible to max.
- Now if we use x painters in the above scenarios, it is obvious that as the value in the range increases, the value of x decreases and vice-versa.
From this we can find the target value when x=k and use a helper function to find x, the minimum number of painters required when the maximum length of section a painter can paint is given.
C++
| // CPP program for painter's partition problem#include <climits>#include <iostream>usingnamespacestd;// return the maximum element from the arrayintgetMax(intarr[], intn){    intmax = INT_MIN;    for(inti = 0; i < n; i++)        if(arr[i] > max)            max = arr[i];    returnmax;}// return the sum of the elements in the arrayintgetSum(intarr[], intn){    inttotal = 0;    for(inti = 0; i < n; i++)        total += arr[i];    returntotal;}// find minimum required painters for given maxlen// which is the maximum length a painter can paintintnumberOfPainters(intarr[], intn, intmaxLen){    inttotal = 0, numPainters = 1;    for(inti = 0; i < n; i++) {        total += arr[i];        if(total > maxLen) {            // for next count            total = arr[i];            numPainters++;        }    }    returnnumPainters;}intpartition(intarr[], intn, intk){    intlo = getMax(arr, n);    inthi = getSum(arr, n);    while(lo < hi) {        intmid = lo + (hi - lo) / 2;        intrequiredPainters            = numberOfPainters(arr, n, mid);        // find better optimum in lower half        // here mid is included because we        // may not get anything better        if(requiredPainters <= k)            hi = mid;        // find better optimum in upper half        // here mid is excluded because it gives        // required Painters > k, which is invalid        else            lo = mid + 1;    }    // required    returnlo;}// driver functionintmain(){    intarr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };    intn = sizeof(arr) / sizeof(arr[0]);    intk = 3;    cout << partition(arr, n, k) << endl;    return0;} | 
Java
| // Java Program for painter's partition problemimportjava.io.*;importjava.util.*;classGFG {    // return the maximum element from the array    staticintgetMax(intarr[], intn)    {        intmax = Integer.MIN_VALUE;        for(inti = 0; i < n; i++)            if(arr[i] > max)                max = arr[i];        returnmax;    }    // return the sum of the elements in the array    staticintgetSum(intarr[], intn)    {        inttotal = 0;        for(inti = 0; i < n; i++)            total += arr[i];        returntotal;    }    // find minimum required painters for given maxlen    // which is the maximum length a painter can paint    staticintnumberOfPainters(intarr[], intn,                                intmaxLen)    {        inttotal = 0, numPainters = 1;        for(inti = 0; i < n; i++) {            total += arr[i];            if(total > maxLen) {                // for next count                total = arr[i];                numPainters++;            }        }        returnnumPainters;    }    staticintpartition(intarr[], intn, intk)    {        intlo = getMax(arr, n);        inthi = getSum(arr, n);        while(lo < hi) {            intmid = lo + (hi - lo) / 2;            intrequiredPainters                = numberOfPainters(arr, n, mid);            // find better optimum in lower half            // here mid is included because we            // may not get anything better            if(requiredPainters <= k)                hi = mid;            // find better optimum in upper half            // here mid is excluded because it gives            // required Painters > k, which is invalid            else                lo = mid + 1;        }        // required        returnlo;    }    // Driver code    publicstaticvoidmain(String args[])    {        intarr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};        // Calculate size of array.        intn = arr.length;        intk = 3;        System.out.println(partition(arr, n, k));    }}// This code is contributed by Sahil_Bansall | 
Python3
| # Python program for painter's partition problem# Find minimum required painters for given maxlen# which is the maximum length a painter can paintdefnumberOfPainters(arr, n, maxLen):    total =0    numPainters =1    fori inarr:        total +=i        if(total > maxLen):            # for next count            total =i            numPainters +=1    returnnumPaintersdefpartition(arr, n, k):    lo =max(arr)    hi =sum(arr)    while(lo < hi):        mid =lo +(hi -lo) //2        requiredPainters =numberOfPainters(arr, n, mid)        # find better optimum in lower half        # here mid is included because we        # may not get anything better        if(requiredPainters <=k):            hi =mid        # find better optimum in upper half        # here mid is excluded because it gives        # required Painters > k, which is invalid        else:            lo =mid +1    # required    returnlo# Driver codearr =[1, 2, 3, 4, 5, 6, 7, 8, 9]n =len(arr)k =3print(int(partition(arr, n, k))) | 
C#
| // C# Program for painter's// partition problemusingSystem;classGFG {    // return the maximum    // element from the array    staticintgetMax(int[] arr, intn)    {        intmax = int.MinValue;        for(inti = 0; i < n; i++)            if(arr[i] > max)                max = arr[i];        returnmax;    }    // return the sum of the    // elements in the array    staticintgetSum(int[] arr, intn)    {        inttotal = 0;        for(inti = 0; i < n; i++)            total += arr[i];        returntotal;    }    // find minimum required    // painters for given    // maxlen which is the    // maximum length a painter    // can paint    staticintnumberOfPainters(int[] arr, intn,                                intmaxLen)    {        inttotal = 0, numPainters = 1;        for(inti = 0; i < n; i++) {            total += arr[i];            if(total > maxLen) {                // for next count                total = arr[i];                numPainters++;            }        }        returnnumPainters;    }    staticintpartition(int[] arr, intn, intk)    {        intlo = getMax(arr, n);        inthi = getSum(arr, n);        while(lo < hi) {            intmid = lo + (hi - lo) / 2;            intrequiredPainters                = numberOfPainters(arr, n, mid);            // find better optimum in lower            // half here mid is included            // because we may not get            // anything better            if(requiredPainters <= k)                hi = mid;            // find better optimum in upper            // half here mid is excluded            // because it gives required            // Painters > k, which is invalid            else                lo = mid + 1;        }        // required        returnlo;    }    // Driver code    staticpublicvoidMain()    {        int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };        // Calculate size of array.        intn = arr.Length;        intk = 3;        Console.WriteLine(partition(arr, n, k));    }}// This code is contributed by ajit | 
PHP
| <?php// PHP program for painter's // partition problem// return the maximum // element from the arrayfunctiongetMax($arr, $n){    $max= PHP_INT_MIN;    for($i= 0; $i< $n; $i++)         if($arr[$i] > $max)            $max= $arr[$i];     return$max;}// return the sum of the// elements in the arrayfunctiongetSum($arr, $n){    $total= 0;    for($i= 0; $i< $n; $i++)        $total+= $arr[$i];    return$total;}// find minimum required painters // for given maxlen which is the// maximum length a painter can paintfunctionnumberOfPainters($arr, $n,                           $maxLen){    $total= 0; $numPainters= 1;    for($i= 0; $i< $n; $i++)    {        $total+= $arr[$i];        if($total> $maxLen)         {            // for next count            $total= $arr[$i];            $numPainters++;        }    }    return$numPainters;}functionpartition($arr, $n, $k){    $lo= getMax($arr, $n);    $hi= getSum($arr, $n);    while($lo< $hi)     {        $mid= $lo+ ($hi- $lo) / 2;        $requiredPainters=                     numberOfPainters($arr,                                      $n, $mid);        // find better optimum in        // lower half here mid is         // included because we may         // not get anything better        if($requiredPainters<= $k)            $hi= $mid;        // find better optimum in         // upper half here mid is         // excluded because it         // gives required Painters > k,        // which is invalid        else            $lo= $mid+ 1;    }    // required    returnfloor($lo);}// Driver Code$arr= array(1, 2, 3,              4, 5, 6,              7, 8, 9);$n= sizeof($arr);$k= 3;echopartition($arr, $n, $k), "\n";// This code is contributed by ajit?> | 
Javascript
| <script>// Javascript Program for painter's partition problem   // Return the maximum element from the arrayfunctiongetMax(arr, n){    let max = Number.MIN_VALUE;    for(let i = 0; i < n; i++)        if(arr[i] > max)            max = arr[i];                returnmax;}// Return the sum of the elements in the arrayfunctiongetSum(arr, n){    let total = 0;    for(let i = 0; i < n; i++)        total += arr[i];            returntotal;}// Find minimum required paleters for given maxlen// which is the maximum length a paleter can paletfunctionnumberOfPaleters(arr, n, maxLen){    let total = 0, numPaleters = 1;    for(let i = 0; i < n; i++)    {        total += arr[i];        if(total > maxLen)         {            // For next count            total = arr[i];            numPaleters++;        }    }    returnnumPaleters;}functionpartition(arr, n, k){    let lo = getMax(arr, n);    let hi = getSum(arr, n);    while(lo < hi)    {        let mid = lo + (hi - lo) / 2;        let requiredPaleters = numberOfPaleters(            arr, n, mid);        // Find better optimum in lower half        // here mid is included because we        // may not get anything better        if(requiredPaleters <= k)            hi = mid;        // find better optimum in upper half        // here mid is excluded because it gives        // required Paleters > k, which is invalid        else            lo = mid + 1;    }    // Required    returnlo;}// Driver codelet arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ];// Calculate size of array.let n = arr.length;let k = 3;document.write(Math.round(partition(arr, n, k)));// This code is contributed by sanjoy_62</script> | 
17
Time Complexity: O(N*log(sum(arr[])))
Auxiliary Space: O(1)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!


 
                                    







