1. 程式人生 > >POJ - 2947 Widget Factory(同餘式的高斯消元)

POJ - 2947 Widget Factory(同餘式的高斯消元)

題目連結

ACCode:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 310;
int mod;
int Equ, Var;      //方程式的個數, 未知數的個數
int A[maxn][maxn]; //增廣矩陣,最後一列是係數
int X[maxn];       //儲存所有的解
bool FreeX[maxn];
int FreeNum;       //自由元的個數

int GCD(int a, int b)
{
    if(b == 0)
        return a;
    else
        return GCD(b, a%b);
}
int LCM(int a, int b)
{
    return a/GCD(a, b) * b;
}

void ex_gcd(int a, int b, int& d, int& x, int& y) //擴充套件歐幾里得求貝祖等式
{
    if(!b){
        d = a; x = 1; y = 0;
    }
    else{
        ex_gcd(b, a%b, d, y, x);
        y -= x*(a/b);
    }
}
//高斯消元主方程
int Gauss_Elimination()
{
    int i, j, k;
    int MaxRow;
    int col = 0;
    int Lcm;
    int ta, tb;
    int temp;
    int FreeXNum, FreeIndex;
    for(int i = 0; i < Var; i++){
        X[i] = 0; FreeX[i] = true;
    }
    for(k = 0; k < Equ && col < Var; k++, col++){
        MaxRow = k;
        for(i = k+1; i < Equ; i++){
            if(abs(A[i][col]) > abs(A[MaxRow][col]))
                MaxRow = i;
        }
        if(MaxRow != k){
            for(j = k; j <= Var; j++)
                swap(A[k][j], A[MaxRow][j]);
        }
        if(A[k][col] == 0){
            k --;
            continue;
        }
        for(i = k+1; i < Equ; i++){
            if(A[i][col]){
                Lcm = LCM(abs(A[i][col]), abs(A[k][col]));
                ta = Lcm / abs(A[i][col]);
                tb = Lcm / abs(A[k][col]);
                if(A[i][col] * A[k][col] < 0) tb = -tb;
                for(j = col; j <= Var; j++)
                    A[i][j] = (A[i][j]*ta%mod - A[k][j]*tb%mod + mod) % mod;
            }
        }
    }
//已經化成階梯型矩陣了
    for(i = k; i < Equ; i++)
        if(A[i][col]) return -1;  //存在 0 0 0 3 這樣的情況,無解
    if(k < Var)                   //存在 0 0 0 0 這樣的情況,有多解
        return Var-k;             //返回自由元的個數

    // 回代
    for(int i = Var-1; i >= 0; i--){
        for(int j = i+1; j < Var; j++){
            A[i][Var] -= ((X[j] * A[i][j]) % mod);
        }
        A[i][Var] = (A[i][Var]%mod + mod) % mod;
        int x, y, d;
        ex_gcd(A[i][i], mod, d, x, y);
        X[i] = (A[i][Var]*x% mod + mod) % mod;
    }
    return 0;
}
char Wed[7][5] = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN" };
int get_id(char *str)
{
    for(int i = 0; i < 7; i++)
        if(!strcmp(Wed[i], str))
            return i;
}

int main()
{
    int num, dur, x;
    char s1[50], s2[50];
    while(scanf("%d %d", &Var, &Equ) && (Var+Equ)){
        memset(A, 0, sizeof(A));
        mod = 7;
        for(int i = 0; i < Equ; i++){
            scanf("%d %s %s", &num, s1, s2);
            int be = get_id(s1), ed = get_id(s2);
            if(be > ed) dur = ed + mod+1 - be;
            else        dur = ed - be + 1;
            A[i][Var] = dur;
            while(num--){
                scanf("%d", &x);
                A[i][x-1] ++;
                A[i][x-1] %= mod;
            }
        }
        int ans = Gauss_Elimination();
        if(ans == -1)    cout << "Inconsistent data." << endl;
        else if(ans > 0) cout << "Multiple solutions." << endl;
        else {
            for(int i = 0; i < Var; i++){
                if(X[i] < 3) X[i] += mod;
                if(X[i] > 9){
                    X[i] %= 7;
                    if(X[i] < 3) X[i] += mod;
                }
                if(i == 0) cout << X[i];
                else       cout << " " << X[i];
            } cout << endl;
        }
    }
    return 0;
}