Блог пользователя WorstCoder45

Автор WorstCoder45, история, 3 года назад, По-английски

Two new shops are opening inside a new building and k kinds of items are needed to stock shelves at each store. Given the prices of n items in two shops, choose exactly k indices in such a way that the minimum sum of arrays firstShop and secondShop over these indices is maximum.

Specifically, choose exactly k indices (i[1], i[2],...., i[k]) such that the value min(a[i[1]]+a[i[2]]+.... + a[i[k]], b1+b[i[2]]+...+b[i[k]]) is maximized. Find this maximum value.

Example:-

n=5, k=3

firstShop=[6, 3, 6, 5, 1]

secondShop = [1, 4, 5, 9, 2]

Choose the subset of indices as (0, 2, 3).

The value is min(6+6+5, 1+5+9)= 15, which is the maximum possible. Return 15 as the answer

1<=N,array-values<=50

My DP Solution :- O(N*K*|sum1|*|sum2|) ; where sum1 = total sum of first array ; sum2 = total sum of second array but it TLE's how to optimize?

dp[i][k][sum1][sum2] = returns true if it is possible to select k indices from (0....i) such that array1 has sum1 and array2 has sum2.

Теги dp
  • Проголосовать: нравится
  • +3
  • Проголосовать: не нравится

»
3 года назад, скрыть # |
← Rev. 4  
Проголосовать: нравится +1 Проголосовать: не нравится

Instead of keeping track of sum1 and sum2 separately only keep track of the difference, since this is enough to determine the proper strategy.

For example, define dp[n'][k'][diff] as the best possible result if you choose k' indices from the first n', and currently sum1 = diff, sum2 = 0.

Then the recurrence is:

$$$\text{dp[n'][k'][diff] = max(dp[n'-1][k'-1][diff] , b[i] + dp[n'-1][k'-1][diff + a[i] - b[i]])}$$$

The first term is if you don't choose index n', the second is if you choose it.

  • »
    »
    3 года назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Pls teach how to notice such recursive methods. I've learned to picture as a tree, but that never works for me.

  • »
    »
    3 года назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Why are you adding min(a[i], b[i]) in diff ?

    • »
      »
      »
      3 года назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      Sorry, it is a mistake. The i should be n' and that should just be b[i]. I was editing my expression and didn't pay close attention.

      The reason is: If you choose index n', then you have to choose k'-1 indices from the first n'-1, and currently sum1 = a[n'] and sum2 = b[n'].

      But only the difference in sum1 and sum2 matter, so the best possible result is b[n'] plus the result if you start with sum1 = a[n']-b[n'] and sum2 = 0.

      • »
        »
        »
        »
        3 года назад, скрыть # ^ |
         
        Проголосовать: нравится 0 Проголосовать: не нравится

        Can you elaborate how dp[n][k][diff] helps in finding final answer ; sum1,sum2 actually tells us they are possible and we take their min for all possible sum1,sum2 and finally print max of all of them how is it possible in dp[n][k][diff]?

        • »
          »
          »
          »
          »
          3 года назад, скрыть # ^ |
           
          Проголосовать: нравится 0 Проголосовать: не нравится

          The final answer should be dp[n][k][0], because you need to choose k indices from the first n, and you start with sum1 = 0, sum2 = 0.

          • »
            »
            »
            »
            »
            »
            3 года назад, скрыть # ^ |
             
            Проголосовать: нравится 0 Проголосовать: не нравится

            dp[n][k][0] means best answer such that sum1 = sum2 that is not the requirement of the problem. sum1 and sum2 can be different

            Am I getting something wrong please clarify and thanks for your precious time!

            • »
              »
              »
              »
              »
              »
              »
              3 года назад, скрыть # ^ |
               
              Проголосовать: нравится 0 Проголосовать: не нравится

              No, dp[n'][k'][diff] means best answer such that you start with sum1 = diff, sum2 = 0, and then try to maximize min(sum1, sum2) by choosing k' indices from the first n'.

              So in the example you gave, dp[2][1][-3] = 1. Why? Because if we start with sum1 = -3, sum2 = 0, and can choose 1 of the first 2 indices, the best thing to do is to choose the first index. Then sum1 = 3, sum2= 1, and our result will be 1.

              Similarly, dp[2][1][7] = 4. If we start with sum1 = 7, sum2 = 0, the best is to choose the second index, which gives a result of 4.

  • »
    »
    3 года назад, скрыть # ^ |
    ← Rev. 6  
    Проголосовать: нравится +3 Проголосовать: не нравится
    Assuming diff = sum1-sum2
    
    dp[n'][k'][diff] = max value in both of them such that by 
                       adding this to sum1 , they can be equal
    Ex:  diff = 3 , dp[n'][k'][diff] =5
         means sum1 = 5 + 3 , sum2 = 5     , 5 is max possible we can make here
    
    Ex:  diff = -3 , dp[n'][k'][diff] = 5
         means sum1 = 5 - 3 , sum2 = 5     , 5 is max possible we can make here
    
    Transiition: (you see in above example that the value that dp store is sum2 right)
                   Thats why we do b[i]
         dp[n'][k'][diff] = max(dp[n'-1][k'-1][diff] , b[i] + dp[n'-1][k'-1][diff + a[i] &mdash; b[i]])
    
         Now in the end, what values we get in diff , if diff > 0 , ans = max(ans , dp[n][k][diff])
                                                      else   ans = max(ans , dp[n][k][diff] - diff)
    
    
»
3 года назад, скрыть # |
 
Проголосовать: нравится +14 Проголосовать: не нравится

$$$dp[i][k][sum1] =$$$ maximum possible $$$sum2$$$

»
2 месяца назад, скрыть # |
 
Проголосовать: нравится -11 Проголосовать: не нравится
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
using ll = long long;
typedef vector<int> vi;

const int NEG = -1000000000;

int dp[55][55][2505];

int fun(vi &arr1, vi &arr2, int ind, int ct, int sum){

    if(ind == arr1.size()){
        if(ct == 0) return 0;
        return NEG;
    }

    if(dp[ind][ct][sum] != -1)
        return dp[ind][ct][sum];

    int ans = NEG;

    ans = max(ans, fun(arr1, arr2, ind + 1, ct, sum));

    if(ct > 0){
        int x = fun(arr1, arr2, ind + 1, ct - 1, sum + arr2[ind]);
        if(x != NEG)
            ans = max(ans, x + arr1[ind]);
    }

    return dp[ind][ct][sum] = ans;
}

This gives a complexity of O(n * k * totalSum) instead of keeping both sums separately.

Am I missing something, or is there a hidden flaw in this approach?

»
5 недель назад, скрыть # |
 
Проголосовать: нравится -10 Проголосовать: не нравится

~~~~~~~~~~
int n, k; vector first, second; int memo[51][51][2501]; const int INF = 1e9;

/*
 * STATE:
 * solve(idx, count, target_a)
 * - idx: Current item index (0 to n-1)
 * - count: Remaining items needed to pick (0 to k)
 * - target_a: Remaining firstShop sum required
 * 
 * RETURNS: Maximum secondShop sum for this exact configuration
 */
int solve(int idx, int count, int target_a) {
    // Base Case 1: Picked required 'k' items
    if (count == 0) {
        return (target_a == 0) ? 0 : -INF;
    }

    // Base Case 2: Out of items or target_a became negative
    if (idx == n || target_a < 0) {
        return -INF;
    }

    // Return memoized result if already calculated
    if (memo[idx][count][target_a] != -1) {
        return memo[idx][count][target_a];
    }

    // Option 1: Skip current item
    int skip = solve(idx + 1, count, target_a);

    // Option 2: Pick current item
    int pick = -INF;
    if (target_a >= first[idx]) {
        int sub_res = solve(idx + 1, count - 1, target_a - first[idx]);
        if (sub_res != -INF) {
            pick = second[idx] + sub_res;
        }
    }

    return memo[idx][count][target_a] = max(skip, pick);
}
int maxMinSum(int n_val, int k_val, vector<int>& firstShop, vector<int>& secondShop) {
    n = n_val;
    k = k_val;
    first = firstShop;
    second = secondShop;

    int max_a_sum = 0;
    for (int x : first) max_a_sum += x;

    // Reset memoization table with -1
    memset(memo, -1, sizeof(memo));

    int ans = 0;

    // Try all possible total sums for firstShop
    for (int sa = 0; sa <= max_a_sum; ++sa) {
        int sb = solve(0, k, sa);
        if (sb >= 0) {
            ans = max(ans, min(sa, sb));
        }
    }

    return ans;
}

~~~~~~

»
5 недель назад, скрыть # |
 
Проголосовать: нравится -18 Проголосовать: не нравится
// Why Not use binary search instead ? 

// The qn is asking to pick k indices such that the minimum ( a[i] + b[i] ) is maximized , right ? 
// Let's Assume say X to be the final answer , then in that case , i should be able to find k-1 elements that are greater than or equal to X , and 1 X . 

// But then this could be simplified to just checking if there are k elements greater than or equal to X , since we try to maximize the X in the binary search


// So , l = 0 , r = max(a)
// Then Binary Search no this range , with the check() evaluating based on the above condition



// Would this work ? Or if it fails can you pls help me understand where it fails or why