[3_2_ratios] Cramer's rule

12 篇文章 0 订阅
Feed Ratios
1998 ACM Finals, Dan Adkins

Farmer John feeds his cows only the finest mixture of cow food, which has three components: Barley, Oats, and Wheat. While he knows the precise mixture of these easily mixable grains, he can not buy that mixture! He buys three other mixtures of the three grains and then combines them to form the perfect mixture.

Given a set of integer ratios barley:oats:wheat, find a way to combine them IN INTEGER MULTIPLES to form a mix with some goal ratio x:y:z.

For example, given the goal 3:4:5 and the ratios of three mixtures:

 
        1:2:3
        3:7:1
        2:1:2

your program should find some minimum number of integer units (the `mixture') of the first, second, and third mixture that should be mixed together to achieve the goal ratio or print `NONE'. `Minimum number' means the sum of the three non-negative mixture integers is minimized.

For this example, you can combine eight units of mixture 1, one unit of mixture 2, and five units of mixture 3 to get seven units of the goal ratio:

 
    8*(1:2:3) + 1*(3:7:1) + 5*(2:1:2) = (21:28:35) = 7*(3:4:5)

Integers in the goal ratio and mixture ratios are all non-negative and smaller than 100 in magnitude. The number of units of each type of feed in the mixture must be less than 100. The mixture ratios are not linear combinations of each other.

PROGRAM NAME: ratios

INPUT FORMAT

Line 1:Three space separated integers that represent the goal ratios
Line 2..4:Each contain three space separated integers that represent the ratios of the three mixtures purchased.

SAMPLE INPUT (file ratios.in)

 
3 4 5
1 2 3
3 7 1
2 1 2

OUTPUT FORMAT

The output file should contain one line containing four integers or the word `NONE'. The first three integers should represent the number of units of each mixture to use to obtain the goal ratio. The fourth number should be the multiple of the goal ratio obtained by mixing the initial feed using the first three integers as mixing ratios.

SAMPLE OUTPUT (file ratios.out)

8 1 5 7











As there are only 1013 = 1,030,301 ways to do this, try them all and pick the best.

 
#include <stdio.h>

/* the goal ratio */
int goal[3];

/* the ratio of the feeds */
int ratios[3][3];

/* the best solution found so far */
int min;
int mloc[4]; /* amounts of ratio 1, 2, and 3, and the amount of ratio 4 prod */

/* the amount of each type of component in the feed */
int sum[3];

int main(int argc, char **argv)
 {
  FILE *fout, *fin;
  int lv, lv2, lv3; /* loop variables */
  int t, s; /* temporary variables */
  int gsum; /* the sum of the amounts of components in the goal mixture */

  if ((fin = fopen("ratios.in", "r")) == NULL)
   {
    perror ("fopen fin");
    exit(1);
   }
  if ((fout = fopen("ratios.out", "w")) == NULL)
   {
    perror ("fopen fout");
    exit(1);
   }

  /* read in data */
  fscanf (fin, "%d %d %d", &goal[0], &goal[1], &goal[2]);
  for (lv = 0; lv < 3; lv++)
    fscanf (fin, "%d %d %d", ratios[lv]+0, ratios[lv]+1, ratios[lv]+2);

  gsum = goal[0] + goal[1] + goal[2];

  min = 301; /* worst than possible = infinity */

  /* boundary case (this ensures gsum != 0) */
  if (gsum == 0)
   {
    fprintf (fout, "0 0 0 0\n");
    return 0;
   }

  for (lv = 0; lv < 100; lv++)
    for (lv2 = 0; lv2 < 100; lv2++)
     { /* for each amout of the first two types of mixtures */
      sum[0] = lv*ratios[0][0] + lv2*ratios[1][0];
      sum[1] = lv*ratios[0][1] + lv2*ratios[1][1];
      sum[2] = lv*ratios[0][2] + lv2*ratios[1][2];

      if (lv + lv2 > min) break;

      for (lv3 = 0; lv3 < 100; lv3++)
       {
        s = lv + lv2 + lv3;
	if (s >= min) break; /* worse than we've found already */

        /* calculate a guess at the multiples of the goal we've obtained */
	/* use gsum so we don't have to worry about divide by zero */
        t = (sum[0] + sum[1] + sum[2]) / gsum;
	if (t != 0 && sum[0] == t*goal[0] && 
	        sum[1] == t*goal[1] && sum[2] == t*goal[2])
	 { /* we've found a better solution! */
	  /* update min */
	  min = s;

	  /* store the solution */
	  mloc[0] = lv;
	  mloc[1] = lv2;
	  mloc[2] = lv3;
	  mloc[3] = t;
	 }

        /* add another 'bucket' of feed #2 */
        sum[0] += ratios[2][0];
        sum[1] += ratios[2][1];
        sum[2] += ratios[2][2];
       }
     }
  if (min == 301) fprintf (fout, "NONE\n"); /* no solution found */
  else fprintf (fout, "%d %d %d %d\n", mloc[0], mloc[1], mloc[2], mloc[3]);
  return 0;
 }

Vlad Novakovski's Solution

When you combine multiples of mixtures, you can look at it as a multiplication of a matrix by a vector. For example, 8*(1:2:3) + 1*(3:7:1) + 5*(2:1:2) = (21:28:35) = 7*(3:4:5) can be seen as

 
[ 1 3 2 ]   [ 8 ]            
[ 2 7 1 ] * [ 1 ] = 7 [3 4 5]
[ 3 1 2 ]   [ 5 ]           

The matrix and the goal ratio vector (3:4:5 in this case) are given; what we have to find is the multiple vector (8:1:5 in this case) and the proportionality costant (7 here). This is like solving a system of linear equations. We can write it as

 
AX = kB.

Now, if we use Cramer's Rule, and let D = determinant of A, then

X_1 = k D_1 / D
X_2 = k D_2 / D
X_3 = k D_3 / D,
where D_1 is the determinant of the matrix A with the 1st column is replaced by B, D_2 is the determinant of the matrix A with the 2nd column is replaced by B, D_3 is the determinant of the matrix A with the 3rd column is replaced by B. (see a Linear Algebra textbook on why this works.) ,P> We are looking for integral solutions. If D = 0, no solutions. Otherwise, let k = D, and then X_1 = D_1, etc. If these values (X_1,X_2,X_3, _and_ k) all have a greatest common factor above 1, divide them all by that factor, as we are looking for the smallest possible solutions.

Now, if some of the numbers is greater than 100, we have not found a feasible solution, so we output `NONE'. Otherwise, the triple (X_1,X_2,X_3) is output, as well as the value k. 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值