Gambler Bo (高斯消元求特解)
Posted wethura
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 ; }
以上是关于Gambler Bo (高斯消元求特解)的主要内容,如果未能解决你的问题,请参考以下文章