This solution is effectively calling the function cost(CNT_PRODUCTS, quantities, costs, meals[m] in parallel. The next meals is served on a new day.
One can brute-force this problem by considering all pairs of shops, and all single-shop visits. If the pairs of shops are equal, that is a single-shop visit. I have provided code snippets with trace.
1.1: Determining Satisfiability of pair
Let satisfiable(i, j, Q) represent the feasibility of the shops visited given Q. The pair i, j is satisfiable if for all products k, the quantities Q[i][k] + Q[j][k] >= meals[m][k]. We can save the Q[i][k] + Q[j][k] in a cubic array S of size O(SHOPS*SHOPS*CNT_PRODUCTS).
Calculating satisfiable(i, j, Q) for all pairs of shops (which will all be considered) can be done by looking up if S[i][j][k] >= meals[m][k] while looping through k.
public static int choosingShops(final int CNT_PRODUCTS, int[][] Q, int[][] C, int[] X) {
boolean satisfiable;
int cost;
int mincost = -1;
// Search through all solos and pairs
for (int i1 = 0; i1 < Q.length; i1++) {
for (int i2 = i1; i2 < Q.length; i2++) {
satisfiable = satisfiesQuantity(CNT_PRODUCTS, Q, X, i1, i2);
if (satisfiable) {
System.out.printf("Shops #%d, #%d is feasible\n", i1, i2);
cost = cost(CNT_PRODUCTS, Q, C, X, i1, i2);
if (mincost == -1 || cost < mincost) {
mincost = cost;
}
}
}
}
return mincost;
}
1.2: Calculating cost
Loop through all the pairs, considering only the satisfiable pairs.
For each satisfiable pair i, j, for each item k, we take as much as possible from the shop i1st which sells item k at a lower price, and if i1st does not supply all of the requirement, take meals[m][k] - Q[i1st][k] from i2nd to satisfy the requirement.
The cost is then calculated for shop i, j. Keep track of the minimum cost achieved so far. Then, the answer at index m is the smallest cost that is required to satisfy the particular meal meals[m] over satisfiable shops.
Calculating cost for each i, j is a linear O(CNT_PRODUCTS) time problem. There is a quadratic amount of pairs you need to consider, and each pair takes O(CNT_PRODUCTS) time to process. The brute-force approach is thus a cubic O(SHOPS*SHOPS*CNT_PRODUCTS) algorithm per meal.
/* Let Q, C, X represent quantity and cost of item
* with row number indicating shop number.
* Let X be the current meal
*/
public static int cost(final int CNT_PRODUCTS, int[][] Q, int[][] C, int[] X, int i1, int i2) {
// Precondition: Must satisfy quantity constraints
int cost = 0;
int i1st, i2nd;
for (int k = 0; k < CNT_PRODUCTS; k++) {
// Two shops
if (i1 < i2) {
// Determine which shop is priority for thhis item
if (C[i1][k] < C[i2][k]) {
i1st = i1;
i2nd = i2;
}
else {
i1st = i2;
i2nd = i1;
}
// Add items to shop
if (Q[i1st][k] >= X[k]) {// If the first shop supplies all
cost += X[k]*C[i1st][k];
System.out.printf("\tBought %d unit%d all from shop #%d for $%d each.\n", X[k], k, i1st, C[i1st][k]);
}
else { // When both shops are required
cost += Q[i1st][k]*C[i1st][k];
cost += (X[k] - Q[i1st][k])*C[i2nd][k];
System.out.printf("\tBought %d unit%d from shop #%d for $%d each.\n", Q[i1st][k], k, i1st, C[i1st][k]);
System.out.printf("\tBought %d unit%d from shop #%d for $%d each.\n", X[k] - Q[i1st][k], k, i2nd, C[i2nd][k]);
}
}
// One shop
else {
cost += X[k]*C[i1][k];
System.out.printf("\tBought %d unit%d from shop #%d for $%d each.\n", X[k], k, i1, C[i1][k]);
}
}
System.out.printf("\tTotal cost is $%d\n\n", cost);
return cost;
}
Optimization
You can determine S once given a list of meals, and determine satisfiability by looking up the S[][][k].
Although I did see that this problem is claimed to be dynamic programming, I don't see an optimal substructure.