1. 程式人生 > >Gambler Bo (高斯消元求特解)

Gambler Bo (高斯消元求特解)

for const ++ c++ scanf swa return print ()

對於圖中的每一個點假設點擊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\n", ans); for(int i = 1; i < cnt; i ++){ while(x[i]){ printf("%d %d\n", (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 ; }

Gambler Bo (高斯消元求特解)