-3

I am trying this problem on SPOJ. Its basically a 0/1 knapsack.

Problem Statement: We are given N≤1000 choice of air tanks having oxygen capacity, nitrogen capacity, and weight O[i], N[i], and W[i] respectively O≤21,N≤79,W≤800. We need enough tanks to fuel t oxygen and a nitrogen respectively to complete the dive. Find the minimum total weight of tanks needed to complete the dive.

I already implemented a 3-D dynamic programming solution. But I am getting Wrong Answer. Please help.

Source Code:

int dp[1002][23][81];   // to store subproblems
int ox[1002],nt[1002],wt[1002]; // ox: oxygen; nt: nitrogen; wt = weight of cylinder

void solve(int n, int oxy, int nit){ // n: no. of cylinders, oxy: oxygen required; nit: nitrogen required
  for(int i = 0; i <=n; ++i)
    for(int j = 0; j <= oxy; ++j)
      for(int k = 0; k <= nit; ++k){
        if(i == 0)
          dp[i][j][k] = INF;
        else if(j == 0 && k == 0)
          dp[i][j][k] = 0;
        else
          dp[i][j][k] = min(dp[i-1][j][k], dp[i-1][max(j-ox[i], 0)][max(k-nt[i], 0)] + wt[i]);
      }
  printf("%d\n", dp[n][oxy][nit]);
}

Please help. Complete Source Code

newuser
  • 31
  • 5
  • Does it work for the sample input ? What have you tried so far in order to debug this ? – Paul R Jan 27 '15 at 07:25
  • Yaa it works for the sample input. I tried it for some other cases. Its working fine. Even looked at some other places. They all point to similar approach. I added link to complete source code. :( – newuser Jan 27 '15 at 07:26
  • 1
    You should edit the whole code into the question, it isn't that long although removing unused headers would make it a bit shorter, and you should add a language tag. – Retired Ninja Jan 27 '15 at 07:37
  • **You should edit the whole code into the question, it isn't that long although removing unused headers would make it a bit shorter**. Please elaborate. I am new here. Meanwhile I added the tag. Don't know much about posting for problems. Thanks for the advice. – newuser Jan 27 '15 at 07:44
  • 1
    There seems to be no step which initializes the array `dp` with the individual values from the given air tanks. Or is this contained in the last `else` branch? Please elaborate a little bit more on the recurrence equation. – Codor Jan 27 '15 at 07:50
  • 2
    [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) – Retired Ninja Jan 27 '15 at 07:50
  • 1
    @Codor `dp[i][j][k] = min(dp[i-1][j][k], dp[i-1][max(j-ox[i], 0)][max(k-nt[i], 0)] + wt[i]);` In this line, the second arguement of min() does the thing. It will include the case, in whcih only that cylinder is included. – newuser Jan 27 '15 at 07:52
  • Strange. The recurrence ralation looks ok to me - it means that the `i`-th tank is *not included* and *included*, respectively, right? – Codor Jan 27 '15 at 08:25
  • 1
    Yes, just like knapsack. – newuser Jan 27 '15 at 08:58
  • 1
    Is it possible that `INF` is defined too small? – Codor Jan 27 '15 at 09:10

1 Answers1

2

The problem is that you are assigning infinite weight (cost) to all cases that use 0 tanks -- including, incorrectly, the case where oxy = nit = 0. In that case (i.e. dp[0][0][0]) the weight assigned should be 0, since you can supply 0 oxygen and 0 nitrogen quite comfortably using 0 tanks.

This bug will cause your code to miss every minimal solution in which the tanks exactly cover the oxygen and nitrogen requirements with none left over, since all of these decision sequences end at the dp[0][0][0] subproblem after the last tank is added to the current partial solution. To fix it, all you need to do is reverse the order of the first two if tests inside your innermost loop.

j_random_hacker
  • 50,331
  • 10
  • 105
  • 169