USACO Feed Ratios, 解线性方程组,克莱姆法则,0取余

C++里, 0 取余(%)任何数为0,比如 0 % 5 = 0 而不是5
暴力枚举:因为因子最大为100,计算量最大100的立方,可以暴力枚举,参考:http://www.cppblog.com/Ylemzy/articles/99550.html (这个代码没有考虑0)
或者 克莱姆法则:http://wenku.baidu.com/view/a50e676c1eb91a37f1115c49.html


我的代码,用的克莱姆法则;注意开始几次没通过,一要注意运用克莱姆法则算ans[i]的时候要检查getDet(map) % getDet(dp) == 0,商为整数才能继续;二是数据源很贱,有的不是最简,结果算出负值,所以输出前要检验

/* 
ID: wangxin12 
PROG: ratios
LANG: C++ 
*/ 
#include <iostream>
#include <fstream>
using namespace std;

int d[3];
int dp[3][3];
int map[3][3];
int ans[4];
ifstream fin("ratios.in");
ofstream fout("ratios.out");

void read() {
	fin>>d[0]>>d[1]>>d[2];
	int i, j;
	for( i = 0; i < 3; i++) {
		for( j = 0; j < 3; j++) {
			fin>>map[j][i];
			dp[j][i] = map[j][i];
		}
	}
}

int getDet(int det[3][3]) {  //计算三行行列式的值
	int ans = det[0][0] * det[1][1] * det[2][2] +
		det[0][1] * det[1][2] * det[2][0] +
		det[1][0] * det[2][1] * det[0][2] -
		det[0][2] * det[1][1] * det[2][0] -
		det[0][1] * det[1][0] * det[2][2] -
		det[0][0] * det[1][2] * det[2][1];
	return ans;
}

void modifyMap(int col, int multiple) { //将行列式的第col列用数组D替换
	int i,j;
	for(i = 0; i < 3; i++)
		for(j = 0; j < 3; j++)
			map[i][j] = dp[i][j];

	for(i = 0; i < 3; i++)
		map[i][col] = d[i] * multiple;
}

bool calculate() {
	int i, j;
	bool f[3];
	for(j = 1; j <= 100; j++) {
		for( i = 0; i < 3; i++) {
			modifyMap(i, j); //j为multiple,从1到100进行试探 
			if( getDet(map) % getDet(dp) == 0) {  //一定注意这里判断能否整除
				ans[i] = getDet(map) / getDet(dp);
				f[i] = true;
			} else {
				f[0] = false; f[1] = false; f[2] = false;
				break;
			}
		}
		if(f[1] == true && f[2] == true && f[0] == true) {
			ans[3] = j;
			//fout<<ans[0]<<" "<<ans[1]<<" "<<ans[2]<<" "<<ans[3]<<endl;
			return true;
		}
	}	
	return false;
}

int main() {
	read();

	if(getDet(dp) == 0) {
		fout<<"NONE"<<endl;
	} else {
		calculate();
		if(ans[0] >= 0 && ans[1] >= 0 && ans[2] >= 0 && ans[3] > 0) //有的源数据不是最简的,可能导致负数答案出现,这里要检查
			fout<<ans[0]<<" "<<ans[1]<<" "<<ans[2]<<" "<<ans[3]<<endl;
		else
			fout<<"NONE"<<endl;	
	}

	fin.close();
	fout.close();
	return 0;
}



描述

农夫约翰从来只用调配得最好的饲料来喂他的奶牛。饲料用三种原料调配成:大麦,燕麦和小麦。他知道自己的饲料精确的配比,在市场上是买不到这样的饲料的。他只好购买其他三种混合饲料(同样都由三种麦子组成),然后将它们混合,来调配他的完美饲料。

给出三组整数,表示 大麦:燕麦:小麦 的比例,找出用这三种饲料调配 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。一种混合物的比例不会由其他混合物的比例直接相加得到。

[编辑]格式

PROGRAM NAME: ratios

INPUT FORMAT:

(file ratios.in)

Line 1: 三个用空格分开的整数,表示目标饲料

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

OUTPUT FORMAT:

(file ratios.out)

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

[编辑]SAMPLE INPUT

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

[编辑]SAMPLE OUTPUT

8 1 5 7

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值