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

题目描述:

农夫约翰从来只用调配得最好的饲料来喂他的奶牛。饲料用三种原料调配成:大麦,燕麦和小麦。他知道自己的饲料精确的配比,在市场上是买不到这样的饲料的。他只好购买其他三种混合饲料(同样都由三种麦子组成),然后将它们混合,来调配他的完美饲料。
给出三组整数,表示 大麦:燕麦:小麦 的比例,找出用这三种饲料调配 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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值