Open In App

Post Box Allocation

Last Updated : 22 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given with array of apartments where apartments[i] is the location of the ith apartment along a street and an integer p postboxes in the street. Return the minimum total distance between each apartment and its nearest postbox.

Examples:

Input : apartments = [ 1 , 4 , 8 , 10 , 20 ] , p = 3
Output : 5
Explanation : We allocate postboxes at location 3 , 9, and 20 . minimum total distance from each apartment to nearest postbox is |3-1| + |4-3| + |9-8| + |10-9| + |20-20| = 5

Input : apartments = [ 2 , 3 , 5 , 12 , 18 ] , p = 2
Output : 9
Explanation : We allocate postboxes at location 3, 14 . minimum total distance from each apartment to nearest postbox is |2-3| + |3-3| + |5-3| + |12-14| + |18-14| = 9

Approach: To solve the problem follow the below idea.

  • We sort our apartments based on the location of the apartments, now we know that any postbox will have its optimal position if it’s kept between any two apartments so that we can minimize the distance of the postbox from both apartments.
  • We store all possible distances sum we can achieve if we keep the postbox at the middle of the desired range in a 2D distance array distance. ( Note: distance array carries the sum of distances of apartments from the postbox ( if kept in the middle of the range) of the particular range).
  • We recursively move to each range i – j and place our postbox in the middle of it, and then increment our total distance sum by the sum of distances of all apartments up to the postbox, decrement the number of postboxes as we placed one in this range and then recursively move to next range, taking the minimum of all the distances we return our answer.

Below is the implementation of the above approach:

C++14




// Include necessary header files
#include <bits/stdc++.h>
using namespace std;
 
// Global variables
int costs[100][100]; // Array to store the costs of placing
                     // postboxes between apartments
int dp[100]
      [100]; // Memoization table for dynamic programming
const int INF
    = 100 * 10000; // A constant representing infinity
 
// Recursive function to find the minimum total distance
int solver(vector<int>& apartments, int n, int p, int i)
{
    // Base case: If all apartments are covered and
    // postboxes are placed, return 0
    if (i == n and p == 0) {
        return 0;
    }
    // Base case: If either all apartments are covered or no
    // more postboxes to place, return INF
    if (i == n or p == 0) {
        return INF;
    }
    // If the result is already calculated, return it
    if (dp[p][i] != -1)
        return dp[p][i];
 
    // Initialize answer to INF
    int ans = INF;
 
    // Try placing a postbox at each position and find the
    // minimum total cost
    for (int j = i; j < n; j++) {
        ans = min(
            ans, costs[i][j]
                     + solver(apartments, n, p - 1, j + 1));
    }
 
    // Memoize the result and return
    return dp[p][i] = ans;
}
 
// Function to calculate the minimum distance
int minDistance(vector<int>& apartments, int p)
{
    int n = apartments.size();
 
    // Sort the apartments in ascending order
    sort(apartments.begin(), apartments.end());
 
    // Initialize dp array with -1
    memset(dp, -1, sizeof dp);
 
    // Calculate costs array representing the distance
    // between apartments[i] and apartments[j]
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            int mid
                = (apartments[(i + j) / 2]); // Calculate
                                             // the midpoint
            for (int k = i; k <= j; k++) {
                // Calculate and accumulate the cost
                costs[i][j] += abs(mid - apartments[k]);
            }
        }
    }
 
    // Call the solver function and return the result
    return solver(apartments, n, p, 0);
}
 
// Main function
int main()
{
    // Example input
    vector<int> apartments = { 1, 4, 8, 10, 20 };
    int p = 4;
 
    // Output the minimum distance
    cout << minDistance(apartments, p);
 
    // Return 0 to indicate successful completion
    return 0;
}


Java




import java.util.Arrays;
import java.util.Vector;
 
public class Main {
 
    // Global variables
    static int[][] costs = new int[100][100]; // Array to store the costs of placing postboxes between apartments
    static int[][] dp = new int[100][100];     // Memoization table for dynamic programming
    static final int INF = 100 * 10000;       // A constant representing infinity
 
    // Recursive function to find the minimum total distance
    static int solver(Vector<Integer> apartments, int n, int p, int i) {
        // Base case: If all apartments are covered and postboxes are placed, return 0
        if (i == n && p == 0) return 0;
        // Base case: If either all apartments are covered or no more postboxes to place, return INF
        if (i == n || p == 0) return INF;
        // If the result is already calculated, return it
        if (dp[p][i] != -1) return dp[p][i];
 
        // Initialize answer to INF
        int ans = INF;
 
        // Try placing a postbox at each position and find the minimum total cost
        for (int j = i; j < n; j++) {
            ans = Math.min(ans, costs[i][j] + solver(apartments, n, p - 1, j + 1));
        }
 
        // Memoize the result and return
        return dp[p][i] = ans;
    }
 
    // Function to calculate the minimum distance
    static int minDistance(Vector<Integer> apartments, int p) {
        int n = apartments.size();
 
        // Sort the apartments in ascending order
        apartments.sort(Integer::compareTo);
 
        // Initialize dp array with -1
        for (int[] row : dp) {
            Arrays.fill(row, -1);
        }
 
        // Calculate costs array representing the distance between apartments[i] and apartments[j]
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int mid = apartments.get((i + j) / 2); // Calculate the midpoint
                for (int k = i; k <= j; k++) {
                    // Calculate and accumulate the cost
                    costs[i][j] += Math.abs(mid - apartments.get(k));
                }
            }
        }
 
        // Call the solver function and return the result
        return solver(apartments, n, p, 0);
    }
 
    // Main function
    public static void main(String[] args) {
        // Example input
        Vector<Integer> apartments = new Vector<>(Arrays.asList(1, 4, 8, 10, 20));
        int p = 4;
 
        // Output the minimum distance
        System.out.println(minDistance(apartments, p));
    }
}
 
// This code is contributed by shivamgupta310570


Python3




import sys
 
# Global variables
costs = [[0] * 100 for _ in range(100)]  # Array to store the costs of placing postboxes between apartments
dp = [[-1] * 100 for _ in range(100)]  # Memoization table for dynamic programming
INF = 100 * 10000  # A constant representing infinity
 
# Recursive function to find the minimum total distance
def solver(apartments, n, p, i):
    # Base case: If all apartments are covered and postboxes are placed, return 0
    if i == n and p == 0:
        return 0
    # Base case: If either all apartments are covered or no more postboxes to place, return INF
    if i == n or p == 0:
        return INF
    # If the result is already calculated, return it
    if dp[p][i] != -1:
        return dp[p][i]
 
    # Initialize answer to INF
    ans = INF
 
    # Try placing a postbox at each position and find the minimum total cost
    for j in range(i, n):
        ans = min(ans, costs[i][j] + solver(apartments, n, p - 1, j + 1))
 
    # Memoize the result and return
    dp[p][i] = ans
    return ans
 
# Function to calculate the minimum distance
def minDistance(apartments, p):
    n = len(apartments)
 
    # Sort the apartments in ascending order
    apartments.sort()
 
    # Initialize dp array with -1
    for i in range(100):
        for j in range(100):
            dp[i][j] = -1
 
    # Calculate costs array representing the distance between apartments[i] and apartments[j]
    for i in range(n):
        for j in range(n):
            mid = apartments[(i + j) // 2# Calculate the midpoint
            for k in range(i, j + 1):
                # Calculate and accumulate the cost
                costs[i][j] += abs(mid - apartments[k])
 
    # Call the solver function and return the result
    return solver(apartments, n, p, 0)
 
# Main function
if __name__ == "__main__":
    apartments = [1, 4, 8, 10, 20]
    p = 4
    print(minDistance(apartments, p))
    sys.exit(0)


C#




using System;
using System.Collections.Generic;
 
class Program
{
    // Global variables
    static int[,] costs; // Array to store the costs of placing postboxes between apartments
    static int[,] dp;    // Memoization table for dynamic programming
    const int INF = 100 * 10000; // A constant representing infinity
 
    // Recursive function to find the minimum total distance
    static int Solver(List<int> apartments, int n, int p, int i)
    {
        // Base case: If all apartments are covered and postboxes are placed, return 0
        if (i == n && p == 0)
        {
            return 0;
        }
        // Base case: If either all apartments are covered or no more postboxes to place, return INF
        if (i == n || p == 0)
        {
            return INF;
        }
        // If the result is already calculated, return it
        if (dp[p, i] != -1)
            return dp[p, i];
 
        // Initialize answer to INF
        int ans = INF;
 
        // Try placing a postbox at each position and find the minimum total cost
        for (int j = i; j < n; j++)
        {
            ans = Math.Min(ans, costs[i, j] + Solver(apartments, n, p - 1, j + 1));
        }
 
        // Memoize the result and return
        return dp[p, i] = ans;
    }
 
    // Function to calculate the minimum distance
    static int MinDistance(List<int> apartments, int p)
    {
        int n = apartments.Count;
 
        // Sort the apartments in ascending order
        apartments.Sort();
 
        // Initialize dp array with -1
        dp = new int[p + 1, n];
        for (int i = 0; i <= p; i++)
        {
            for (int j = 0; j < n; j++)
            {
                dp[i, j] = -1;
            }
        }
 
        // Calculate costs array representing the distance between apartments[i] and apartments[j]
        costs = new int[n, n];
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                int mid = apartments[(i + j) / 2]; // Calculate the midpoint
                for (int k = i; k <= j; k++)
                {
                    // Calculate and accumulate the cost
                    costs[i, j] += Math.Abs(mid - apartments[k]);
                }
            }
        }
 
        // Call the solver function and return the result
        return Solver(apartments, n, p, 0);
    }
 
    // Main function
    static void Main()
    {
        // Example input
        List<int> apartments = new List<int> { 1, 4, 8, 10, 20 };
        int p = 4;
 
        // Output the minimum distance
        Console.WriteLine(MinDistance(apartments, p));
    }
}


Javascript




// Global variables
const costs = Array.from({ length: 100 }, () => Array(100).fill(0)); // Array to store the costs of placing postboxes between apartments
const dp = Array.from({ length: 100 }, () => Array(100).fill(-1)); // Memoization table for dynamic programming
const INF = 100 * 10000; // A constant representing infinity
 
// Recursive function to find the minimum total distance
function solver(apartments, n, p, i) {
    // Base case: If all apartments are covered and postboxes are placed, return 0
    if (i === n && p === 0) {
        return 0;
    }
    // Base case: If either all apartments are covered or no more postboxes to place, return INF
    if (i === n || p === 0) {
        return INF;
    }
    // If the result is already calculated, return it
    if (dp[p][i] !== -1) {
        return dp[p][i];
    }
 
    // Initialize answer to INF
    let ans = INF;
 
    // Try placing a postbox at each position and find the minimum total cost
    for (let j = i; j < n; j++) {
        ans = Math.min(ans, costs[i][j] + solver(apartments, n, p - 1, j + 1));
    }
 
    // Memoize the result and return
    dp[p][i] = ans;
    return ans;
}
 
// Function to calculate the minimum distance
function minDistance(apartments, p) {
    const n = apartments.length;
 
    // Sort the apartments in ascending order
    apartments.sort((a, b) => a - b);
 
    // Calculate costs array representing the distance between apartments[i] and apartments[j]
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            const mid = apartments[Math.floor((i + j) / 2)]; // Calculate the midpoint
            for (let k = i; k <= j; k++) {
                // Calculate and accumulate the cost
                costs[i][j] += Math.abs(mid - apartments[k]);
            }
        }
    }
 
    // Call the solver function and return the result
    return solver(apartments, n, p, 0);
}
 
// Main function
const apartments = [1, 4, 8, 10, 20];
const p = 4;
console.log(minDistance(apartments, p));


Output

2









Time Complexity : O(n3)
Auxiliary Space Complexity : O(n2) , n is the number of apartment



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads