fammy - 8 months ago 48

Java Question

I'm doing a Knapsack in Java where we only use weights no value. The weightlimit is 1000. We get 5 weights scanned from keyboard which we use.

The twist is that you can actually go over 1000 aslong as its the closets to 1000. So in one scenario we have 2 possible weights 990 and 1010 and the program is suposed to pick the higher one.

The scanned numbers can never be higher then 1000.

`package kapsackidone;`

import java.util.Scanner;

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.*;

public class Kapsack {

public static void main(String[] args) throws Exception {

BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));

int [] wt=new int[5];

int W = 1000;

System.out.println("Enter Weight 5 weights");

for(int i=0; i<5; i++)

{

wt[i]=Integer.parseInt(reader.readLine());

}

System.out.println(knapsack(wt, W));

}

public static int knapsack(int wt[], int W) {

int N = wt.length;

int[][] V = new int[N + 1][W + 1];

for (int col = 0; col <= W; col++) {

V[0][col] = 0;

}

for (int row = 0; row <= N; row++) {

V[row][0] = 0;

}

for (int item=1;item<=N;item++){

for (int weight=1;weight<=W;weight++){

if(wt[item-1] > weight)

{

V[item][weight] = V[item-1][weight];

}

else if((weight - V[item-1][weight]) < (weight - (V[item-1][weight - wt[item-1]] + wt[item-1])))

{

V[item][weight] = V[item-1][weight];

}

else

{

V[item][weight] = V[item-1][weight - wt[item-1]] + wt[item-1];

}

}

}

return V[N][W];

}

}

I am really struggling with how I can get this done.

Before you ask no its not homework im gonna be a project manager for a new group of people that consist of developers so im just trying to learn some java so that i understand a bit of what they do even tho i doubt i will be able to help with the coding.

Answer

I would just run it twice.

In first run find the "classic" solution with best weight less than 1000.

In second run, increase the max value 1000 to the max possible value which is allowed based on previous solution.

Dont worry about "it is two times slower", multiplying complexity by constant does not change the complexity, which is the important thing in knapsack problem.

If your code is working then you can probably count the best solution as this

```
System.out.println(knapsack(wt,2*W - knapsack(wt, W));
```

Or you can write it as this to be more clear what is happening (it does exactly the same as that one-line above)

```
int bestClassicSolution = knapsack(wt, W);
int differenceAgainstMaxWeight = W - bestClassicSolution;
int newMaxWeight = W + differenceAgainstMaxWeight;
int bestSolution = knapsack(wt, newMaxWeight);
System.out.println(bestSolution);
```

EDIT : The solution above works for this condition `select as big solution as possible, but it must not differ from 1000 more than "below 1000" best solution`

. The OP actually wants little different thing - the "limit" stays, but it should be the closest to the 1000 but as high as possible.

So real solution would to create reversed knapsack method, which will find the solution with minimum value BUT must be bigger than "min" variable.

```
public static void main(String[] args) throws Exception {
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
int [] wt=new int[5];
int W = 1000;
System.out.println("Enter Weight 5 weights");
for(int i=0; i<5; i++)
{
wt[i]=Integer.parseInt(reader.readLine());
}
int bestClassicSolution = knapsack(wt, W);
int differenceAgainstMaxWeight = W - bestClassicSolution;
int newMaxWeight = W + differenceAgainstMaxWeight;
int bestMaxSolution = reversedKnapsack(wt, newMaxWeight, W);
int differenceAgainstWeightAboveW = W - bestMaxSolution;
if (differenceAgainstWeightAboveW <= differenceAgainstMaxWeight){
System.out.println(bestMaxSolution);
} else {
System.out.println(bestClassicSolution);
}
}
public static int reversedKnapsack(int wt[], int W, int min) {
//similar to knapsack method, but the solution must be as small as possible and must be bigger than min variable
}
```