Dynamic Programing approach for a subset sum

前端 未结 4 519
借酒劲吻你
借酒劲吻你 2021-01-15 09:20

Given the following Input

10 4 3 5 5 7

Where

10 = Total Score

4 = 4 players

3 = Score by player 1

5 = Score by player 2
         


        
4条回答
  •  情话喂你
    2021-01-15 10:04

    Your problem is in this part of the code

                if(arr[i] < x)
                {
                    myArray[i][x] = myArray[i-1][x];
                }
                else
                {
                    myArray[i][x] = myArray[i-1][x-arr[i]];
                }
    

    You have two situations

    1. (inside if)We already found a set in this case you need carry previous result to next one.
    2. (inside else) After subtracting result become false, but previous result is true. so you need to carry that result.

    why? [3, 34, 4, 12, 5, 2]

    Do not forget the part that DP has Optimal Substructure properties. For, finding sum is 9 we have to find all the sum before it, means 1 to 8. That is exactly you are doing by declaring a W+1 row. So when we calculate sum is 7, for first three values we have a result [3,34,4], we need to carry that result to next level.

    So you need to modify previous code, to this

               myArray[i][x] = myArray[i-1][x];//carrying previous result
                if(x>=arr[i] )
                {
                    if (myArray[i][x]==1){
                        myArray[i][x]=1; 
                    }
                    else{
                        myArray[i][x] = myArray[i-1][x-arr[i]];
                    }
                }
    

    You also have array indexing issue. Your i and x both start from 1 and you never consider the index 0 which is actually your first player. you need to take arr[i-1] value

    so further update will look like this,

            myArray[i][x] = myArray[i-1][x];//carrying previous result
                    if(x>=arr[i-1] )
                    {
                        if (myArray[i][x]==1){
                            myArray[i][x]=1; 
                        }
                        else{
                            myArray[i][x] = myArray[i-1][x-arr[i-1]];
                        }
                    }
    

    So final program will look like this

        public boolean findSolution(int[] scores, int total) {
        int W = total;
        int players = scores.length;
    
        boolean[][] myArray = new boolean[players + 1][total + 1];
    
        for (int player = 0; player <= players; player++) {
            myArray[player][0] = true;
        }
        for (int score = 1; score < total; score++) {
            myArray[0][score] = false;
        }
        for (int player = 1; player <= players; player++) {
            for (int score = 1; score <= total; score++) {
                myArray[player][score] = myArray[player - 1][score];
                if (score >= scores[player - 1]) {
                    myArray[player][score] = myArray[player - 1][score
                            - scores[player - 1]]
                            || myArray[player][score];
                }
            }
        }
        return myArray[players][W];
    
    }
    

    Now for printing result, look into true values in the matrix. it shouldn't be difficult to find out which values are set and when it was set. print those index to get the result.

提交回复
热议问题