【USACO 3.2.4】飼料調合純整数ガウス消元
2175 ワード
実はガウス消元です.
しかし定数項は未知であるが,定数項は必ず題目で与えられた定数の整数倍(K倍)であるため,このKを窮挙してGauss消元する.
しかしNONEをどう判断するのか.手間を省いて、何度も繰り返して、ずっと解けないで、解がありません.
最近ガウス消元のテンプレートを書かなければなりませんが...
しかし定数項は未知であるが,定数項は必ず題目で与えられた定数の整数倍(K倍)であるため,このKを窮挙してGauss消元する.
しかしNONEをどう判断するのか.手間を省いて、何度も繰り返して、ずっと解けないで、解がありません.
最近ガウス消元のテンプレートを書かなければなりませんが...
/*
TASK:ratios
LANG:C++
*/
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
const int max_n = 5;
int equ, var;// , var equ ,var +1 ( )
int a[max_n][max_n], ta[max_n][max_n];
int x[max_n]; //
int gcd(int a, int b){return a == 0 ? b : gcd(b % a , a);}
int lcm(int a, int b){return a / gcd(a, b) * b;}
bool guess()
{
int row=0, col=0; // ,
for (; row != equ && col != var; ++ row, ++ col)
{
int max_row = row;
for (int i = row + 1; i != equ; ++ i) if (a[i][col] > a[max_row][col]) max_row = i;
if (!a[max_row][col]) return false;
for (int i = col; i <= var; ++ i) swap(a[row][i], a[max_row][i]);
for (int i = row + 1; i != equ; ++ i)
{
if (!a[i][col]) continue;
int tmp = lcm(abs(a[row][col]), abs(a[i][col]));
int ta = tmp / a[row][col]; // ,
int tb = tmp / a[i][col];
for (int j = col; j <= var; ++ j) a[i][j] = a[i][j] * tb - a[row][j] * ta;
}
}
row = equ - 1, col = var - 1;
for (;row >= 0; -- row, -- col)
{
int tmp = a[row][var];
for (int i = col + 1; i != var; ++ i) tmp -= a[row][i] * x[i];
if (tmp % a[row][col]) return false;
x[col] = tmp / a[row][col];
if (x[col] < 0) return false;
}
return true;
}
void init()
{
for (int i = 0; i != 3; ++ i) cin >> ta[i][var];
for (int i = 0; i != 3; ++ i)
for (int j = 0; j != 3; ++ j) cin >> ta[j][i];
}
void doit()
{
for (int ans = 1; ans <= 100; ++ ans)
{
for (int i = 0; i != 3; ++ i)
for (int j = 0; j != 4; ++ j) a[i][j] = ta[i][j];
for (int i = 0; i != 3; ++ i) a[i][3] *= ans;
if (guess())
{
for (int i = 0; i != var; ++ i) cout<<x[i]<<" ";
cout<<ans<<endl;
return;
}
}
cout<<"NONE"<<endl;
}
int main()
{
// freopen("ratios.in","r",stdin);
// freopen("ratios.out","w",stdout);
equ = var = 3;
init();
doit();
return 0;
}