0

I encountered this problem practicing for an upcoming national competition. The problem goes as follows: You need to create a mixture of two ingredients being in relation to 1:1. You are given N different mixtures, each having its own weight Wi, and its relation in the mixture between the ingredients Mi, Ti (Each value, N, Wi, Mi, and Ti, will be less than 100). We need to find the biggest possible weight of the final mixture, keeping the relation to 1:1. We can take from each given mixture how much we want, we don't necessarily need to take the whole mixture, we can take some portion of it.

So with the given relation 1:1 in the final mixture, we know that we need to have an equal amount of weight from both ingredients possible. After that I need to know if I take K grams of some mixture, how much weight that is for ingredients A and B. So I came up with the following formula:

Let W be the weight in grams, and M and T be the relation between the ingredients respectively. If we want to take K (K <= W) grams we have the following:

Weight of ingredient A = M * (K / (M+T))

Weight of ingredient B = T * (K / (M+T))

#include <bits/stdc++.h>
using namespace std;
class state{
    public:
        int weight;
        int A;
        int B;
};
int n;
vector<state> arr;
double ans= 0;
void f(double weight_A, double weight_B, int idx){
    if(weight_A == weight_B)
        ans = max(ans, weight_A + weight_B);
    if(idx >= n)
        return;
        
    int weight = arr[idx].weight, relA = arr[idx].A, relB = arr[idx].B;
    for(int K = 0; K <= weight; K++){
        f(weight_A + relA * (K * 1.0/(relA + relB)), weight_B + relB * (K * 1.0/(relA + relB)), idx+1);
    }
}
int main(){
    cin>>n;
    for(int i = 0; i < n; i++){
        state in;
        cin>>in.weight>>in.A>>in.B;
        arr.push_back(in);
    }
    f(0.0, 0.0, 0);
    cout<<fixed<<setprecision(8);
    cout<<ans<<endl;
}

The problem I encountered was that we don't necessarily need to take integer weights, some times to achieve the maximum possible weight of the final product we need to take decimal weights. Let's take a look at this example:

5
14 3 2
4 1 3
4 2 2
6 6 1
10 4 3

We have N = 5, and in each row are given 3 integers, Wi, Mi, and Ti. The weight of the ith mixture and its relation. My solution for this example gives 20.0000, and the correct solution for the above example is 20.85714286. Looking back my initial idea won't work because of the decimal numbers. I suppose there is some formula but I can't figure it out, can anyone help?

Costantino Grana
  • 3,132
  • 1
  • 15
  • 35
Ivan Zanov
  • 11
  • 1
  • my guess, you wrote a program to do it and you used ints instead of doubles and / or you used literals like '1' instead of '1.0'. If you use ints everything is rounded down to the nearest whole number – pm100 Mar 08 '22 at 19:18
  • 1
    but without any code this will get closed quickly, because it looks like you want us to do the work – pm100 Mar 08 '22 at 19:19
  • 9
    Honestly, this question has nothing to do with C++. This is a math question. – PaulMcKenzie Mar 08 '22 at 19:26
  • 1
    A question on Stack Overflow should also be clear and unambiguous. Take some time to think about what question you are seeking an answer to - it is probably not a question that would have a one-word answer, like "can anyone help?" – Drew Dormann Mar 08 '22 at 19:29
  • 1
    Not direct answer, but related to your code: https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h – nanofarad Mar 08 '22 at 19:43
  • Your explanation is still a bit confusing. It sounds like you're trying to paraphrase the original problem instead of providing the exact problem specification. This seems like the kind of problem more suited to a dynamic programming solution, rather than recursion. And I doubt you should be doing any kind of floating point math apart from the final output, since this deals in ratios. Feels kinda similar to the Knapsack Problem actually. – paddy Mar 08 '22 at 20:40
  • Here's the initial problem, https://pastebin.com/bfY23HD7 – Ivan Zanov Mar 08 '22 at 21:06

1 Answers1

0

This is a Linear Programming problem, so you can solve it by constructing the problem in standard form, and then solve it with an optimization algorithm, like the simplex algorithm.

The objective is to maximize the quantity of medicine (from the original problem), that is the sum of quantities taken from each jar (I'll call the quantities x1, x2, ...).

The quantities are bounded to be lower than the weight Wi available in each jar.

The constraint is that the total amount of honey (first ingredient) is equal to the total amount of tahini (second ingredient). This would mean that:

sum(Mi/(Mi+Ti)*xi) = sum(Ti/(Mi+Ti)*xi)

You can take the second summation to the LHS and get:

sum((Mi-Ti)/(Mi+Ti)*xi) = 0

In order to get integer multipliers just multiply everything by the least common multiple of the denominators lcm(Mi+ti) and then divide by the gcd of the coefficients.

Using your example, the constraint would be:

(3-2)/(3+2) x1 + (1-3)/(1+3) x2 + (2-2)/(2+2) x3 + (6-1)/(6+1) x4 + (4-3)/(4+3) x5 = 0

that is

1/5 x1 -2/4 x2 + 0/4 x3 + 5/7 x4 + 1/7 x5 = 0

Multiply by the lcm(5,4,4,7,7)=140:

28 x1 -70 x2 + 0 x3 + 100 x4 + 20 x5 = 0

divide by 2:

14 x1 -35 x2 +0 x3 + 50 x4 + 10 x5 = 0

We are ready to solve the problem. Let's write it in CPLEX format:

maximize
    quantity: x1 + x2 + x3 + x4 + x5
subject to
    mix: 14 x1 -35 x2 +0 x3 + 50 x4 + 10 x5 = 0
bounds
    x1 <= 14
    x2 <= 4
    x3 <= 4
    x4 <= 6
    x5 <= 10
end

Feed it to GLPK:

#include <stdio.h>
#include <stdlib.h>
#include <glpk.h>

int main(void)
{
    glp_prob *P;
    P = glp_create_prob();
    glp_read_lp(P, NULL, "problem.cplex");
    glp_adv_basis(P, 0);
    glp_simplex(P, NULL);
    glp_print_sol(P, "output.txt");
    glp_delete_prob(P);
    return 0;
}

And the output is:

Problem:    
Rows:       1
Columns:    5
Non-zeros:  4
Status:     OPTIMAL
Objective:  quantity = 20.85714286 (MAXimum)

   No.   Row name   St   Activity     Lower bound   Upper bound    Marginal
------ ------------ -- ------------- ------------- ------------- -------------
     1 mix          NS             0             0             =     0.0714286 

   No. Column name  St   Activity     Lower bound   Upper bound    Marginal
------ ------------ -- ------------- ------------- ------------- -------------
     1 x1           B        2.85714             0            14 
     2 x2           NU             4             0             4           3.5 
     3 x3           NU             4             0             4             1 
     4 x4           NL             0             0             6      -2.57143 
     5 x5           NU            10             0            10      0.285714 

Karush-Kuhn-Tucker optimality conditions:

KKT.PE: max.abs.err = 0.00e+00 on row 0
        max.rel.err = 0.00e+00 on row 0
        High quality

KKT.PB: max.abs.err = 0.00e+00 on row 0
        max.rel.err = 0.00e+00 on row 0
        High quality

KKT.DE: max.abs.err = 0.00e+00 on column 0
        max.rel.err = 0.00e+00 on column 0
        High quality

KKT.DB: max.abs.err = 0.00e+00 on row 0
        max.rel.err = 0.00e+00 on row 0
        High quality

End of output

Of course given your input you should construct the problem in memory and feed it to the simplex algorithm without going through a file. Additionally, there's no need to get integer coefficients, it was just to allow a nicer problem formulation.

Costantino Grana
  • 3,132
  • 1
  • 15
  • 35