USACO-Section3.2 Feed Ratios【克莱默法则】

xiaoxiao2021-02-28  30

题目描述:

农夫约翰从来只用调配得最好的饲料来喂他的奶牛。饲料用三种原料调配成:大麦,燕麦和小麦。他知道自己的饲料精确的配比,在市场上是买不到这样的饲料的。他只好购买其他三种混合饲料(同样都由三种麦子组成),然后将它们混合,来调配他的完美饲料。 给出三组整数,表示 大麦:燕麦:小麦 的比例,找出用这三种饲料调配 x:y:z 的饲料的方法。 例如,给出目标饲料 3:4:5 和三种饲料的比例: 1:2:3 3:7:1 2:1:2 你必须编程找出使这三种饲料用量最少的方案,要是不能用这三种饲料调配目标饲料,输出“NONE”。“用量最少”意味着三种饲料的用量(整数)的和必须最小。

对于上面的例子,你可以用8份饲料1,1份饲料2,和5份饲料3,来得到7份目标饲料: 8*(1:2:3) + 1*(3:7:1) + 5*(2:1:2) = (21:28:35) = 7*(3:4:5) 表示饲料比例的整数以及目标饲料的都是小于100的非负整数。表示各种饲料的份数的整数,都小于100。一种混合物的比例不会由其他混合物的比例直接相加得到。

INPUT FORMAT:

Line 1: 三个用空格分开的整数,表示目标饲料 Line 2..4: 每行包括三个用空格分开的整数,表示农夫约翰买进的饲料的比例

OUTPUT FORMAT:

输出文件要包括一行,这一行要么有四个整数,要么是“NONE”。前三个整数表示三种饲料的份数,用这样的配比可以得到目标饲料。第四个整数表示混合三种饲料后得到的目标饲料的份数。


SAMPLE INPUT

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


SAMPLE OUTPUT

8 1 5 7


解题思路:

将方程列出来之后就发现是解三元一次方程组问题,不过最后一行可以乘以1个正整数。原本打算用高斯消元法解决,但是逛了一下nocow后发现了利用克莱默法则的解法,代码更加简洁明了。

#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<algorithm> using namespace std; int a[3],b[3],c[3],d[3]; int fun(int a[],int b[],int c[]){//三阶行列式计算公式 return a[0]*(b[1]*c[2]-c[1]*b[2])-a[1]*(b[0]*c[2]-c[0]*b[2])+a[2]*(b[0]*c[1]-c[0]*b[1]); } int gcd(int a,int b){ return b?gcd(b,a%b):a; } int main(){ FILE *fin = fopen ("ratios.in", "r"); FILE *fout = fopen ("ratios.out", "w"); fscanf(fin,"%d%d%d",&d[0],&d[1],&d[2]); fscanf(fin,"%d%d%d",&a[0],&a[1],&a[2]); fscanf(fin,"%d%d%d",&b[0],&b[1],&b[2]); fscanf(fin,"%d%d%d",&c[0],&c[1],&c[2]); int d0=fun(a,b,c);//系数矩阵 int d1=fun(d,b,c);//结果1矩阵, x1=d1/d0 int d2=fun(a,d,c);//结果2矩阵, x2=d2/d0 int d3=fun(a,b,d);//结果3矩阵,x3=d3/d0 if(d0<0){ d0=-d0;d1=-d1;d2=-d2;d3=-d3; } if(d0==0||d1<0||d2<0||d3<0) fprintf(fout,"NONE\n"); else{ int temp=gcd(d0,gcd(d1,gcd(d2,d3))); fprintf(fout,"%d %d %d %d\n",d1/temp,d2/temp,d3/temp,d0/temp); } exit(0); }
转载请注明原文地址: https://www.6miu.com/read-2621710.html

最新回复(0)