Gambler Bo (高斯消元求特解)

对于图中的每一个点假设点击Xi * m + j 然后每个点都有那么对于每一个点可以列举出一个方程式,n*m个点解n*m个未知数。利用高斯消元就可以解决。

问题就在这个题目可能不止有一个特,所以我们需要求解的时特解。然后那一个求解的我看不懂。

#include <bits/stdc++.h>
using namespace std ;

const int maxn = 35 * 35;
int n, m, cnt;
int id[35][35], data[35][35], a[maxn][maxn], x[maxn];

int gcd(int a, int b){
    return b?gcd(b, a%b) : a;
}

int lcm(int a, int b){
    return a / gcd(a, b) * b;
}

void init(){
    memset(x, 0, sizeof(x));
    memset(a, 0, sizeof(a));
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= m; j ++){
            a[id[i][j]][cnt] = (3 - data[i][j])%3;
            a[id[i][j]][id[i][j]] = 2;
            if( i > 1) a[id[i][j]][id[i - 1][j]] = 1;
            if( j > 1) a[id[i][j]][id[i][j - 1]] = 1;
            if( i < n) a[id[i][j]][id[i + 1][j]] = 1;
            if( j < m) a[id[i][j]][id[i][j + 1]] = 1;
        }
    }
}

void gaussi(){
    for(int i = 1; i < cnt; i ++){
        int top = i;
        for(int j = i + 1; j < cnt; j ++)
            top = abs(a[j][i]) > abs(a[top][i]) ? j : top;
        if(a[top][i]){
            for(int j = i; j <= cnt; j ++)
                swap(a[top][j], a[i][j]);
            for(int j = i + 1; j < cnt; j ++)
            if(a[j][i]){
                int d = lcm(a[j][i], a[i][i]);
                int x1 = d/a[j][i], x2 = d/a[i][i];
                for(int k = i; k <= cnt; k ++)
                    a[j][k] = ((a[j][k] * x1 - a[i][k] * x2)%3 + 3) % 3;
            }
        }
    }
    int ans = 0;
    for(int i = cnt - 1; i > 0; i --){
        x[i] = a[i][cnt];
        for(int j = i + 1; j < cnt; j ++)
            x[i] = ((x[i] - a[i][j] * x[j])%3 + 3)%3;
        x[i] = a[i][i] * x[i] % 3;
        ans += x[i];
    }
    printf("%d
", ans);
    for(int i = 1; i < cnt; i ++){
        while(x[i]){
            printf("%d %d
", (i - 1)/m + 1, (i - 1)%m + 1);
            x[i] --;
        }
    }

}

int main () {
    int T ;scanf("%d",&T);
    while(T -- ){
        cnt = 1;
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= m; j ++)
                scanf("%d",&data[i][j]), id[i][j] = cnt++;
        init();
        gaussi();
    }
    return 0 ;
}
more crazy more get!
原文地址:https://www.cnblogs.com/wethura/p/9795752.html