高斯消元题集
高斯消元本质上不过是线性代数中对矩阵进行的初等变换而已,结题的关键是如何构造出增广矩阵,再看方程的类型,比如整数解、浮点数解、模线性方程、或者求自由变元的数目等等再分别用不同的方式解决即可。
关于高斯消元的原理,可以参考我的另一篇博客:高斯消元原理
HDU: 3976 4818
POJ: 1222 1830 2065 2947 3185
HDU 3976
Electric resistance
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 284;
const double eps = 1e-9;
double a[MAXN][MAXN];
double x[MAXN];
int free_x[MAXN];
int Gauss(int equ, int var) {
int col, max_r;
for(int k = 0, col = 0; k < equ && col < var; ++k, ++col) {
max_r = k;
for(int i = k + 1; i < equ; ++i) {
if(fabs(a[i][col]) > fabs(a[max_r][col])) max_r = i;
}
if(fabs(a[max_r][col]) < eps) return 0; // No solution
if(max_r != k) {
for(int j = col; j < var; ++j) {
swap(a[k][j], a[max_r][j]);
}
swap(x[k], x[max_r]);
}
x[k] /= a[k][col];
for(int j = col + 1; j < var; ++j) a[k][j] /= a[k][col];
a[k][col] = 1;
for(int i = 0; i < equ; ++i) {
if(i != k) {
x[i] -= x[k] * a[i][col];
for(int j = col + 1; j < var; ++j) a[i][j] -= a[k][j] * a[i][col];
a[i][col] = 0;
}
}
}
return 1;
}
int main() {
int T, cas = 1;
scanf("%d", &T);
while(T--) {
int n, m;
scanf("%d %d", &n, &m);
int u, v, w;
memset(a, 0, sizeof(a));
while(m--) {
scanf("%d %d %d", &u, &v, &w);
a[u-1][v-1] += 1.0 / w;
a[u-1][u-1] += -1.0 / w;
a[v-1][u-1] += 1.0 / w;
a[v-1][v-1] += -1.0 / w;
}
for(int i = 0; i < n; ++i) x[i] = 0;
x[0] = 1;
for(int i = 0; i < n; ++i) {
a[n-1][i] = 0;
}
a[n-1][0] = 1;
Gauss(n, n);
printf("Case #%d: %.2f\n", cas++, x[n-1]);
}
return 0;
}
RP problem
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 284;
const double eps = 1e-6;
double a[MAXN][MAXN], x[MAXN];
int equ, var;
int Gauss() {
int col, max_r;
for(int k = 0, col = 0; k < equ && col < var; ++k, ++col) {
max_r = k;
for(int i = k + 1; i < equ; ++i) {
if(fabs(a[i][col]) > fabs(a[max_r][col])) {
max_r = i;
}
}
if(fabs(a[max_r][col]) < eps) return 0; // No solution
if(max_r != k) {
for(int j = col; j < var; ++j) {
swap(a[k][j], a[max_r][j]);
}
swap(x[k], x[max_r]);
}
x[k] /= a[k][col];
for(int j = col + 1; j < var; ++j) a[k][j] /= a[k][col];
a[k][col] = 1;
for(int i = 0; i < equ; ++i) {
if(i != k) {
x[i] -= x[k] * a[i][col];
for(int j = col + 1; j < var; ++j) a[i][j] -= a[k][j] * a[i][col];
a[i][col] = 0;
}
}
}
return 1;
}
vector<int> linker[MAXN];
int g[MAXN][MAXN], deg[MAXN], add[MAXN];
inline void init(int n) {
for(int i = 0 ; i < n; ++i) {
linker[i].clear();
deg[i] = x[i] = 0;
}
memset(g, 0, sizeof(g));
memset(a, 0, sizeof(a));
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n, m;
scanf("%d %d", &n, &m);
equ = var = n;
init(n);
int u, v;
while(m--) {
scanf("%d %d", &u, &v);
if(u == v) continue;
g[u][v] = 1;
}
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
if(j != i && g[i][j]) {
deg[i]++;
linker[j].push_back(i);
}
}
}
for(int i = 0; i < n; ++i) {
a[i][i] = -1;
for(int j = 0; j < linker[i].size(); ++j) {
int v = linker[i][j];
if(i == v) continue;
a[i][v] = 1.0 / deg[v];
}
}
for(int i = 0; i < n; ++i) {
a[n-1][i] = 1;
}
x[n-1] = 1;
for(int k = 0; k < n-1; ++k) {
if(g[n-1][k] == 0) {
for(int i = 0; i < n-1; ++i) {
if(g[n-1][i]) a[i][var] = 1.0 / (deg[n-1] + 1);
else a[i][var] = 0;
}
a[k][var] = 1.0 / (deg[n-1] + 1);
a[n-1][var] = 1;
add[var] = k;
var++;
}
}
if(!Gauss()) {
puts("INF");
continue;
}
double now = x[n-1];
int ans = -1;
for(int i = n; i < var; ++i) {
if(x[n-1] / a[n-1][i] > now) {
ans = add[i];
now = x[n-1] / a[n-1][i];
}
}
printf("1 %d\n", ans);
}
return 0;
}
POJ 1222
EXTENDED LIGHTS OUT
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 128;
int a[MAXN][MAXN];
int x[MAXN];
bool free_x[MAXN];
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int lcm(int a, int b) {
return a / gcd(a, b) * b;
}
int Gauss(int equ, int var) {
for(int i = 0; i <= var; ++i) {
x[i] = 0;
free_x[i] = true;
}
int max_r;
for(int col = 0, row = 0; col < var && row < equ; ++col, ++row) {
max_r = row;
for(int i = row + 1; i < equ; ++i) {
if(abs(a[max_r][col]) < abs(a[i][col])) {
max_r = i;
}
}
if(max_r != row) {
for(int j = row; j < var + 1; ++j) {
swap(a[row][j], a[max_r][j]);
}
}
if(a[row][col] == 0) {
row--;
continue;
}
for(int i = row + 1; i < equ; ++i) {
if(a[i][col] != 0) {
for(int j = col; j < var + 1; ++j) {
a[i][j] ^= a[row][j];
}
}
}
}
for(int i = var - 1; i >= 0; --i) {
x[i] = a[i][var];
for(int j = i + 1; j < var; ++j) {
x[i] ^= (a[i][j] & x[j]);
}
}
return 0;
}
int main() {
int T, cas = 1;
scanf("%d", &T);
while(T--) {
memset(a, 0, sizeof(a));
for(int i = 0; i < 30; ++i) {
scanf("%d", &a[i][30]);
}
for(int i = 0; i < 5; ++i) {
for(int j = 0; j < 6; ++j) {
int t = i * 6 + j;
a[t][t] = 1;
if(i > 0) a[(i - 1) * 6 + j][t] = 1;
if(i < 4) a[(i + 1) * 6 + j][t] = 1;
if(j > 0) a[i * 6 + j - 1][t] = 1;
if(j < 5) a[i * 6 + j + 1][t] = 1;
}
}
Gauss(30, 30);
printf("PUZZLE #%d\n", cas++);
for(int i = 0; i < 30; ++i) {
printf("%d", x[i]);
if((i + 1) % 6 == 0) printf("\n");
else printf(" ");
}
}
return 0;
}
POJ 1830
开关问题
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 284;
const double eps = 1e-6;
int a[MAXN][MAXN];
int x[MAXN];
int free_x[MAXN];
int Gauss(int equ, int var) {
int k, max_r, col, ta, tb;
for(int i = 0; i <= var; ++i) {
x[i] = 0;
free_x[i] = 1;
}
for(k = 0, col = 0; k < equ && col < var; ++k, ++col) {
max_r = k;
for(int i = k + 1; i < equ; ++i) {
if(abs(a[i][col]) > abs(a[max_r][col])) max_r = i;
}
if(max_r != k) {
for(int i = k; i < var + 1; ++i) swap(a[max_r][i], a[k][i]);
}
if(a[k][col] == 0) {
k--;
continue;
}
for(int i = k + 1; i < equ; ++i) {
if(a[i][col] != 0) {
for(int j = col; j < var + 1; ++j) {
a[i][j] ^= a[k][j];
}
}
}
}
for(int i = k; i < equ; ++i) {
if(a[i][col] != 0) return -1;
}
return var - k;
}
int st[MAXN], en[MAXN];
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
for(int i = 0; i < n; ++i) scanf("%d", st + i);
for(int i = 0; i < n; ++i) scanf("%d", en + i);
memset(a, 0, sizeof(a));
int u, v;
while(scanf("%d %d", &u, &v), u || v) {
a[v-1][u-1] = 1;
}
for(int i = 0; i < n; ++i) a[i][i] = 1;
for(int i = 0; i < n; ++i) a[i][n] = st[i] ^ en[i];
int ans = Gauss(n, n);
if(ans == -1) {
puts("Oh,it's impossible~!!");
} else {
printf("%d\n", 1 << ans);
}
}
return 0;
}
POJ 2065
SETI
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int MAXN = 108;
const int inf = 0x7fffffff;
int n, mod;
int a[MAXN][MAXN];
int x[MAXN];
bool free_x[MAXN];
char str[MAXN];
int quickPow(int a, int p, int mod) {
int ans = 1;
a %= mod;
while(p) {
if(p & 1) {
ans = (ans * a % mod) % mod;
}
a = a * a % mod;
p >>= 1;
}
return ans;
}
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int lcm(int a, int b) {
return a / gcd(a, b) * b;
}
int Gauss(int equ, int var, int mod) {
int k, max_r;
int col;
int ta, tb;
int LCM;
int tmp;
int free_x_num;
int free_index;
for(int i = 0; i <= var; ++i) {
x[i] = 0;
free_x[i] = true;
}
col = 0;
for(k = 0; k < equ && col < var; ++k, ++col) {
max_r = k;
for(int i = k + 1; i < equ; ++i) {
if(abs(a[i][col]) < abs(a[max_r][col])) max_r = i;
}
if(max_r != k) {
for(int j = k; j < var + 1; ++j) swap(a[k][j], a[max_r][j]);
}
if(a[k][col] == 0) {
k--;
continue;
}
for(int i = k + 1; i < equ; ++i) {
if(a[i][col] != 0) {
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(int j = col; j < var + 1; ++j) {
a[i][j] = ((a[i][j] * ta - a[k][j] * tb) % mod + mod) % mod;
}
}
}
}
for(int i = var - 1; i >= 0; --i) {
tmp = a[i][var];
for(int j = i + 1; j < var; ++j) {
if(a[i][j] != 0) tmp -= a[i][j] * x[j];
tmp = (tmp % mod + mod) % mod;
}
while(tmp % a[i][i] != 0) tmp += mod;
x[i] = (tmp / a[i][i]) % mod;
}
return 0;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
memset(a, 0, sizeof(a));
scanf("%d %s", &mod, &str);
n = strlen(str);
for(int i = 0; i < n; ++i) {
if(str[i] != '*') {
a[i][n] = str[i] - 'a' + 1;
} else {
a[i][n] = 0;
}
for(int j = 0; j < n; ++j) {
a[i][j] = quickPow(i + 1, j, mod);
}
}
Gauss(n, n, mod);
for(int i = 0; i < n; ++i) {
if(i == n - 1) printf("%d\n", x[i]);
else printf("%d ", x[i]);
}
}
return 0;
}
POJ 2947
Widget Factory
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int MAXN = 328;
const int mod = 7;
const int inf = 0x7fffffff;
int a[MAXN][MAXN];
int x[MAXN];
bool free_x[MAXN];
map<string, int> mp;
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int lcm(int a, int b) {
return a / gcd(a, b) * b;
}
int Gauss(int equ, int var, int mod) {
int i, j, k;
int max_r, col;
int ta, tb;
int LCM, tmp;
int free_x_num;
int free_index;
for(int i = 0; i <= var; ++i) {
x[i] = 0;
free_x[i] = true;
}
col = 0;
for(k = 0; k < equ && col < var; k++, col++) {
max_r = k;
for(i = k + 1; i < equ; ++i) {
if(abs(a[i][col]) > abs(a[max_r][col])) max_r = i;
}
if(max_r != k) {
for(j = k; j < var + 1; ++j) swap(a[k][j], a[max_r][j]);
}
if(a[k][col] == 0) {
k--;
continue;
}
for(i = k + 1; i < equ; ++i) {
if(a[i][col] != 0) {
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 + 1; ++j) {
a[i][j] = ((a[i][j] * ta - a[k][j] * tb) % mod + mod) % mod;
}
}
}
}
for(i = k; i < equ; ++i) {
if(a[i][col] != 0) return -1; // No Solution
}
if(k < var) return var - k; // Infinity solutions
for(int i = var - 1; i >= 0; --i) {
tmp = a[i][var];
for(int j = i + 1; j < var; ++j) {
if(a[i][j] != 0) tmp -= a[i][j] * x[j];
tmp = (tmp % mod + mod) % mod;
}
while(tmp % a[i][i] != 0) tmp += mod;
x[i] = (tmp / a[i][i]) % mod;
}
return 0;
}
int main() {
mp["MON"] = 1;
mp["TUE"] = 2;
mp["WED"] = 3;
mp["THU"] = 4;
mp["FRI"] = 5;
mp["SAT"] = 6;
mp["SUN"] = 7;
int n, m;
char d1[20], d2[20];
while(scanf("%d %d", &n, &m), n || m) {
memset(a, 0, sizeof(a));
int k;
for(int i = 0; i < m; ++i) {
scanf("%d%s%s", &k, &d1, &d2);
a[i][n] = mp[d2] - mp[d1] + 1;
// cerr << a[i][n] << endl;
int id;
while(k--) {
scanf("%d", &id);
a[i][id - 1]++;
a[i][id - 1] %= 7;
}
}
// test starts
/*
cerr << " n = " << n << " m = " << m << endl;
for(int i = 0; i < m; ++i) {
for(int j = 0; j < n + 1; ++j) {
cerr << a[i][j] << " ";
}
cout << endl;
}
*/
// test ends
int ans = Gauss(m, n, mod);
// test starts
/*
cerr << " ans = " << ans << endl;
for(int i = 0; i < n; ++i) {
cerr << x[i] << " ";
}
*/
// test ends
if(ans == 0) {
for(int i = 0; i < n; ++i) {
if(x[i] <= 2) x[i] += 7;
}
for(int i = 0; i < n; ++i) {
if(i == n - 1) printf("%d\n", x[i]);
else printf("%d ", x[i]);
}
}
else if(ans == -1) {
puts("Inconsistent data.");
} else {
puts("Multiple solutions.");
}
}
return 0;
}
POJ 3185
The Water Bowls
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x7fffffff;
const int MAXN = 27;
int a[MAXN][MAXN];
int x[MAXN];
//高斯消元法解模线性方程组
bool free_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;
}
// 高斯消元法解方程组
//-2表示有浮点数解,但无整数解
//-1表示无解
//0表示唯一解
//大于0表示无穷解,并返回自由变元的个数
//有equ个方程,var个变元
//增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var.
int Gauss(int equ, int var, int mod) {
int i, j, k;
int max_r;//当前这列绝对值最大的行.
int col;//当前处理的列
int ta, tb;
int LCM;
int temp;
int free_x_num;
int free_index;
for (int i = 0; i <= var; i++) {
x[i] = 0;
free_x[i] = true;
}
//转换为阶梯阵.
col = 0;//当前处理的列
for (k = 0; k < equ && col < var; k++, col++) {
// 枚举当前处理的行.
// 找到该col列元素绝对值最大的那行与第k行交换(为了在除法时减小误差)
max_r = k;
for (i = k + 1; i < equ; i++) {
if (abs(a[i][col]) > abs(a[max_r][col])) max_r = i;
}
if (max_r != k) {// 与第k行交换.
for (j = k; j < var + 1; j++) swap(a[k][j], a[max_r][j]);
}
if (a[k][col] == 0) {// 说明该col列第k行以下全是0了,则处理当前行的下一列.
k--;
continue;
}
for (i = k + 1; i < equ; i++) {// 枚举要删去的行.
if (a[i][col] != 0) {
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 + 1; j++) {
a[i][j] = ((a[i][j] * ta - a[k][j] * tb) % mod + mod) % mod;
}
}
}
}
//无解的情况
for (i = k; i < equ; i++) {
if (a[i][col] != 0) return -1;
}
//找出和最小的解
int ans = INF;
for (int state = 0; state < (1 << (var - k)); state++) {
int cnt = 0;
for (int i = 0; i < var - k; i++)
if (state & (1 << i))x[i + k] = 1, cnt++;
else x[i + k] = 0;
for (int i = k - 1; i >= 0; i--) {
temp = a[i][var];
for (j = i + 1; j < var; j++) {
if (a[i][j] != 0) temp -= a[i][j] * x[j];
temp = (temp % mod + mod) % mod;
}
while (temp % a[i][i] != 0) temp += mod;
x[i] = (temp / a[i][i]) % mod;
cnt += x[i];
}
ans = min(ans, cnt);
}
return ans;
}
int main() {
int n = 20;
memset(a, 0, sizeof(a));
for (int i = 0; i < 20; ++i) {
scanf("%d", &a[i][n]);
}
for (int i = 0; i < n; ++i) {
a[i][i] = 1;
if (i > 0) a[i - 1][i] = 1;
if (i < n - 1) a[i + 1][i] = 1;
}
int ans = Gauss(n, n, 2);
printf("%d\n", ans);
return 0;
}