USACO Training "Feed Ratios"

USACO Training: "Feed Ratios"

Problem Idea

Given four triple ratios (i.e. 3:4:5) named a, b, c, and t, find the values x, y, z, and k such that xa+yb+zc = kt.

For example, given the ratios 1:2:3, 3:7:1, 2:1:2, and 3:4:5, x, y, z, and k would be 8, 1, 5, and 7 respectively since
    8*(1:2:3) + 1*(3:7:1) + 5*(2:1:2) = (21:28:35) = 7*(3:4:5)

Notices

  1. This is not a unbounded exact knapsack problem. Ironically, DP would be too slow, since we'd need to check for all values of k (the knapsack is not fixed as t!)
  2. There is at most 100 of each feed bag, it is fast enough to enumerate through bag counts themselves.
  3. k can never be 0 (or else x, y, and z will all be 0, but then the goal ratio has to be 0:0:0)
  4. If there is multiple satisfying (x, y, z, k), we choose the one that has smallest value of x+y+z
  5. #4 leads to the possible optimization such that when enumerating, if x+y or x+y+z exceeds the current best value of x+y+z, we don't even need to check if a k exsists 

Code

 /*
TASK: ratios
ID: qlstudi3
LANG: C++14
*/
#include <algorithm>
#include <fstream>
using namespace std;

ifstream cin("ratios.in");
ofstream cout("ratios.out");

int gr[5], tot[5], gt;
int fr[5][5];
int mi, mr[5], mm;

int main()
{
    cin >> gr[0] >> gr[1] >> gr[2];
    gt = gr[0] + gr[1] + gr[2];
    if(gt == 0)
    {
        cout << "0 0 0 0" << endl;
        return 0;
    }
    for(int i=0; i<3; i++)
        cin >> fr[i][0] >> fr[i][1] >> fr[i][2];
     
    mi = 305;
    for(int ff=0; ff<100; ff++)
        for(int sf=0; sf<100; sf++)
        {
            tot[0] = ff*fr[0][0] + sf*fr[1][0];
            tot[1] = ff*fr[0][1] + sf*fr[1][1];
            tot[2] = ff*fr[0][2] + sf*fr[1][2];
            if(ff+sf > mi) continue;
            for(int tf=0; tf<100; tf++)
            {
                if(ff+sf+tf > mi) continue;
                int factor=(tot[0]+tot[1]+tot[2])/gt;
                if(factor != 0 && factor*gr[0] == tot[0] && factor*gr[1] == tot[1] && factor*gr[2] == tot[2])
                {
                    mi = ff+sf+tf;
                    mm = factor;
                    mr[0] = ff; mr[1] = sf; mr[2] = tf;
                }
                tot[0] += fr[2][0];
                tot[1] += fr[2][1];
                tot[2] += fr[2][2];
            }
        }
 
    if(mi == 305) cout << "NONE" << endl;
    else cout << mr[0] << " " << mr[1] << " " << mr[2] << " " << mm << endl;
}

Comments

Popular posts from this blog

USACO Training "subset": Subset Sums

USACO 2018 Open: Talent Show

UVA 787 and Big Number Multiplication