Ho usato delle parole strane perché l'esercizio che hai proposto sembra il compito di un qualche esame di "algoritmi e programmazione" di una qualche facoltà di informatica.
Esistono dei metodi standardizzati er risolvere questo tipo di problemi, ed usarene altri potrebbe rendere la soluzione molto difficile.

Prima di tutto definisco i termini tecnici che ho usato

Ricorsione: Effetto di una chiamata a funzione ricorsiva.
Una funzione ricorsiva è unafunzione che chiama se stessa in maniera tale da trasformare un grosso problema in tanti problemi più piccoli della stessa natura, per esempio, fattoriale (x) = x*fattoriale(x-1).

Backtracking: Quando un problema viene trattato per mezzo di ricorsione, si costruiscono delle soluzioni pezo per pezzo, montanto un nuovo pezzo su quello precedente fino a quando si riesce.
Quando non si è più in grado di proseguire si smonta un pezzo, per poi provare a montarne altri (se ce ne sono) oppure si smonta un altro pezzo ancora (se non ci sono altri pezzi da provare dopo).
La "retromarcia" è detta backtracking ed è il procedimento mediante il quale si esplorano tutte le soluzioni provando ogni possibile combinazioni dei dati in ingresso.

Strategia greedy: Un metodo intelligente che permette di evitare di esplorare tutte le combinazioni ma che garantisce di trovare un risultato abbastanza buono, però non è detto che trovi l'ottimo.

Parametro di ottimo: formalizzazione del criterio di valutazione di un risultato.

Troppa teoria ora guardiamo una possibile base di dati.

1) un vettore di contenitori

Potremmo usare un vettore di interi, ma è più chiaro chiamare le cose con il proprio nome.
I campi del contentore potrebbero essere

typedef struct {int ID ; int capacità ; bool usato; } contenitore;

2)Poi ci servono un paio di interi per i due liquidi magari ridefinendo int come LIQUIDO .

3)Ci serve anche un tipo in grado di immagazzinare una soluzione

soluzione deve contenere un vettore variabile di interi e magari il suo parametro di ottimo

typedef struct (int ** taniche, int valoreDiOttimo)soluzione;

4) un vettore di soluzioni per A e uno per B

soluzione ** A,
B;

---------------------------------------------

dichiaro la base di dati

contenitore ** tanica = ottieniAbbastanzaMemoria(numeroTaniche);

soluzione ** A,
** B;

LIQUIDO A = quantitàDiA,
B = quantitàDiB;

Per la soluzione del problema ci servono una funzione ricorsiva ed una per valutare gli abbinamenti di tutte le soluzioni per A con tutte quelle per B di cui parleremo poi, piano piano.

L'algoritmo per trovare l'ottimo, a livello terra-terra è

1) trovo tutte le combinazioni di taniche che esauriscono completamente A (senza avanzi o disavanzi) e le salvo in un vettore
2) trovo tutte le combinazioni di taniche che esauriscono B A (senza avanzi o disavanzi) e le salvo in un vettore
3) paragono ogni soluzione di A con ogni soluzione di B e valuto

a) se sono compatibili: cioè se non ci sono dei contenitori usati da entrambe le soluzioni, oppure se violano delle altre clausole del problema

b) quanto vale la differenza tra il numero di taniche riepite usando A ed il numero di taniche riempite usando B.

4) confronto la coppia di soluzioni con la coppia che temporaneamente detiene il primato e, nel caso il nuovo valore di ottimo sia migliore, sovrascrivo la precedente.

Se esiste un ottimo, alla fine del procedimento sar trovato.