-1

Here is the Mixing Milk Problem

The Merry Milk Makers company buys milk from farmers, packages it into attractive 1- and 2-Unit bottles, and then sells that milk to grocery stores so we can each start our day with delicious cereal and milk.

Since milk packaging is such a difficult business in which to make money, it is important to keep the costs as low as possible. Help Merry Milk Makers purchase the farmers' milk in the cheapest possible manner. The MMM company has an extraordinarily talented marketing department and knows precisely how much milk they need each day to package for their customers.

The company has contracts with several farmers from whom they may purchase milk, and each farmer has a (potentially) different price at which they sell milk to the packing plant. Of course, a herd of cows can only produce so much milk each day, so the farmers already know how much milk they will have available.

Each day, Merry Milk Makers can purchase an integer number of units of milk from each farmer, a number that is always less than or equal to the farmer's limit (and might be the entire production from that farmer, none of the production, or any integer in between).

Given:

The Merry Milk Makers' daily requirement of milk The cost per unit for milk from each farmer The amount of milk available from each farmer calculate the minimum amount of money that Merry Milk Makers must spend to meet their daily need for milk.

Line 1: Two integers, N and M.

The first value, N, (0 <= N <= 2,000,000) is the amount of milk that Merry Milk Makers wants per day. The second, M, (0 <= M <= 5,000) is the number of farmers that they may buy from.

Lines 2 through M+1:

The next M lines each contain two integers: Pi and Ai. Pi (0 <= Pi <= 1,000) is price in cents that farmer i charges. Ai (0 <= Ai <= 2,000,000) is the amount of milk that farmer i can sell to Merry Milk Makers per day.


My Solution:

My solution was to store the farmers' prices of milk and the quantities of milk they have in a HashMap. As long as there was still milk to buy, I would add the lowest price * the quantity of the lowest price of milk from the HashMap to the cost, as I sorted an ArrayList that stored the costs of milk. Because it is possible that more milk is purchased than needed, I have an if statement that checks that if more milk is purchased than needed, the extra cost is subtracted. I then remove the lowest price from the ArrayList

Code:

The code works for all of the test cases, except from the last one, where there is too much data to put in the question so I'll have it linked to a Google Document.

Input and Output: https://docs.google.com/document/d/10I3b0z17kP_LZzD2lBlH-Igoe6NPybZleD9tNYonqSQ/edit?usp=sharing

/*
ID: henry.d2
LANG: JAVA
TASK: milk
*/

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class milk
{
    public static void main(String[] args) throws IOException
    {
        BufferedReader br = new BufferedReader(new FileReader("milk.in"));

        String[] components = br.readLine().split(" ");

        int n = Integer.parseInt(components[0]); // Get the amount of milk that Merry Milk Makers wants per day (N)
        int m = Integer.parseInt(components[1]); // Get the number of farmers that they may buy from (M)

        Map<Integer, Integer> farmerAndPrice = new HashMap<Integer, Integer>(); // HashMap that stores the prices of milk and quantities
        List<Integer> prices = new ArrayList<Integer>(); // ArrayList that stores the prices for milk

        // Read in P(i) (The price in cents that farmer i charges) and A(i) (The amount of milk that farmer i can send to MMM per day)
        for (int i = 0; i < m; i++)
        {
            String[] pAndA = br.readLine().split(" ");

            int Pi = Integer.parseInt(pAndA[0]);
            int Ai = Integer.parseInt(pAndA[1]);

            farmerAndPrice.put(Pi, Ai); // Add price and quantity to HashMap
            prices.add(Pi); // Add price to ArrayList
        }

        Collections.sort(prices);

        int milkToBuy = 0;
        int cost = 0;

        while (milkToBuy < n) // The farmers still have milk to buy from
        {
            cost += farmerAndPrice.get(prices.get(0)) * prices.get(0);
            milkToBuy += farmerAndPrice.get(prices.get(0));

            if (milkToBuy > n) // If we buy more milk than we need
            {
                cost -= (milkToBuy - n) * prices.get(0);
            }

            System.out.println(prices.toString());

            prices.remove(0);
        }

        File file = new File("milk.out"); // Output to milk.out
        PrintWriter printWriter = new PrintWriter(file);

        printWriter.println(cost);

        printWriter.close();
    }
}
Henry Zhu
  • 2,488
  • 9
  • 43
  • 87

2 Answers2

1

I'm pretty confident that you haven't correctly considered what happens when multiple farmers are selling their milk for the same price.

The way you are using your hash map means that you will overwrite values from previous farmers.

moreON
  • 1,977
  • 17
  • 19
  • Thanks, I understand that now. I changed using a HashMap to using an ArrayList of int[] arrays. – Henry Zhu Feb 19 '16 at 20:55
  • @Henry another option would have been just storing the total amount of milk available at each price (adding them together as you encounter each farmer with a previously encountered price). If you carefully analyse what information you need, you'll find that which discrete farmer is supplying the milk becomes irrelevant after you know what quantity is available for each price. -- maybe that is what you did, it's actually not clear, but still, the dictionary (perhaps better realised by TreeMap than HashMap, given the need to sort) would have worked. – moreON Feb 22 '16 at 03:51
0

Another solution is storing the milk amount and unit price provided by each farmer in a structure and then sorting the structure according to lowest unit price. Then you can iterate through the array list under a loop(until required units becomes 0).

I don't know what the java code is, but here is the c++ code I used to submit to the USACO website:

#include <iostream>
#include <fstream>

typedef struct _PandQ
{
    int milkAmount;
    int unitPrice;
}PandQ;

PandQ *sortInput(int nOfFarmers,PandQ arrUnitPrices[])
{
    for(int iCtr=1;iCtr<nOfFarmers;iCtr++)
    {
        for(int jCtr=0;jCtr<nOfFarmers-iCtr;jCtr++)
        {
            if(arrUnitPrices[jCtr].unitPrice>arrUnitPrices[jCtr+1].unitPrice)
            {
                swap(arrUnitPrices[jCtr],arrUnitPrices[jCtr+1]);
            }
        }
    }
    return arrUnitPrices;
}

int main()
{
    ofstream fout("milk.out");
    ifstream fin("milk.in");
    int reqUnits,nOfFarmers,leastPriceTally,totPrice=0,temp=0,remainder;
    int milkCtr=0;
    PandQ *arrUnitPrices;
    fin>>reqUnits>>nOfFarmers;

    arrUnitPrices=new PandQ[nOfFarmers];
    /*
        to take in values of prices of farmers' milk and amount each farmer has (from file).
    */
    for(int iCtr=0;iCtr<nOfFarmers;iCtr++)
    {
        fin>>arrUnitPrices[iCtr].unitPrice;
        fin>>arrUnitPrices[iCtr].milkAmount;
    }

    arrUnitPrices=sortInput(nOfFarmers,arrUnitPrices);

    while(reqUnits>0)
    {
        if(arrUnitPrices[milkCtr].milkAmount<reqUnits)
        {
            totPrice+=arrUnitPrices[milkCtr].milkAmount*arrUnitPrices[milkCtr].unitPrice;
            reqUnits-=arrUnitPrices[milkCtr].milkAmount;
        }
        else if(arrUnitPrices[milkCtr].milkAmount>=reqUnits)
        {
            totPrice+=reqUnits*arrUnitPrices[milkCtr].unitPrice;
            reqUnits=0;
        }
        milkCtr++;
    }
    fout<<totPrice<<"\n";
}