Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What kind of algorithm? (Knapsack, Bin Packing!?)

The Problem is the following:

You have n trip lengths in km which should be divided among m number of days such that the maximum sum of lengths per day is minimized. E.g. The Trip lengths [1,5,2,6,8,3,2] divided among 3 days result in [1,5,2] [6] [8,3,2] because the maximum of the day length sums is the lowest we can achieve.

Is there a kind of algorithm that describes the handling of such a problem? I came across bin packing and the knapsack problem, but none of them covers my issue. I can imagine it might be a little modification of the bin packing but don't come to a conclusion.

like image 755
Igle Avatar asked Aug 23 '16 08:08

Igle


People also ask

What is the best bin packing algorithm?

The best existing algorithm for optimal bin packing is due to Martello and Toth (Martello & Toth 1990a; 1990b). We present a new algorithm for optimal bin packing, which we call bin completion, that explores a different problem space, and appears to be asymptotically faster than the Martello and Toth algorithm.

What is first fit algorithm in bin packing?

First-fit (FF) is an online algorithm for bin packing. Its input is a list of items of different sizes. Its output is a packing - a partition of the items into bins of fixed capacity, such that the sum of sizes of items in each bin is at most the capacity.

What is the use of knapsack algorithm?

The knapsack problem is an optimization problem used to illustrate both problem and solution. It derives its name from a scenario where one is constrained in the number of items that can be placed inside a fixed-size knapsack.

Can the bin packing problem be solved using integer programming?

The problem of material requirements planning can be formalized as a bin-packing problem, which can be solved using a mixed-integer linear program (MILP).


2 Answers

This problem can be solved using Binary Search

Assume that the maximum length is X , we can easily check if we can divide the trips into m days with maximum length for each day is not greater than X by this following greedy:

boolean isValid(int X){
   int currentLength = 0;
   int numberOfDays = 1;
   for(int i = 0; i < n; i++)
      if (trip[i] > X)
         return false;
      if(currentLength + trip[i] <= X){
         currentLength += trip[i];  
      }else{
         currentLength = trip[i];
         numberOfDays++;
      }
   }
   return numberOfDays <= m;
}

Then, we can easily find the minimum for X by the following binary search:

int start = 0;
int end = sum of all trips;
int result = end;
while(start <=end){
    int mid = (start + end)/2;
    if(isValid(mid)){
       result = mid;
       end = mid - 1;
    }else{
       start = mid + 1;
    }
}

Time complexity is O(n log z) with z is the sum of all trips.

like image 133
Pham Trung Avatar answered Sep 29 '22 19:09

Pham Trung


It can be solved using a Dynamic Programming approach where the state is defined as DP[i][j] where i refers to the ending index of a day and j keeps the count of the days so far. You can move to the next state and take the maximum sum of a day corresponding to the current move and then can compare it to the overall minimum.

I have written a recursive Dynamic programming solution in c++, it might be a little tough to understand as to how the state transitions are working you might need to look into Dynamic programming with memoisation to understand it.

#include <iostream>
#define INF 1000000000
using namespace std;

int n, m, dist[100] = {1,5,2,6,8,3,2}, dp[1000][1000];

int solve(int index, int count){
    if(index == n){
        if(count == m) return 0;
        else return INF;
    }
    if(dp[index][count] != -1) return dp[index][count];
    int sum = 0, ans = INF;
    for(int i = index;i < n;i++){
        sum += dist[i];
        int val = max(sum, solve(i+1, count+1));
        ans = min(ans, val);
    }
    return dp[index][count] = ans;
}

int main() {
    // your code goes here
    n = 7, m = 3;
    for(int i = 0;i < 1000;i++) for(int j = 0;j < 1000;j++) dp[i][j] = -1;
    cout << solve(0, 0) << endl;
    return 0;
}

Link to solution Ideone : https://ideone.com/glHsgF

like image 34
uSeemSurprised Avatar answered Sep 29 '22 17:09

uSeemSurprised