传送门:点击打开链接
思路:高斯消元。。
没学线代前看了好久的高斯消元都没看懂,感觉线代书里的高斯消元讲的详细多了。。
然后网上找过关于高斯消元的代码,几乎没有能返回是否有解,有几组解等的代码-_-
然后今天写了一天,也总算完成了
大概的思路也就是做出梯形矩阵,然后判断矩阵的秩,详细推荐参考线性代数的书会比较好
如果不想弄懂也行,,反正模板已弄好了,以后可以直接套模板
下面是模板
const double exps = 1e-8;
typedef vector<double> vec;
typedef vector<vec> mat;
int dcmp(double x) {
if(fabs(x) < exps) return 0;
return x < 0 ? -1 : 1;
}
void guass(mat &A, int m, int n) {
for(int i = 0; i < m; i++) {
int pv = i, id;
for(int j = 0; j <= n; j++) {
for(int k = i + 1; k < m; k++) {
if(fabs(A[k][j]) > fabs(A[pv][j])) {
pv = k;
}
}
if(dcmp(A[pv][j])) break;
}
swap(A[i], A[pv]);
for(id = 0; id <= n && !dcmp(A[i][id]); id++);
if(id > n) return;
for(int j = i + 1; j < m; j++) {
if(!dcmp(A[j][id])) continue;
double f = A[j][id] / A[i][id];
for(int k = id + 1; k <= n; k++) A[j][k] -= A[i][k] * f;
A[j][id] = 0;
}
}
}
/*
A是增广矩阵
n表示未知数个数,下标从0开始,下标n中的表示等号右边
-1表示无解,0表示多组解,1表示唯一一组解
如果是唯一解,会保存在A[i][n]中
*/
int solve(mat &A) {
int m = A.size(), n = A[0].size() - 1;
guass(A, m, n);
int r1 = 0, r2 = 0;
for(int i = 0; i < m; i++) {
bool sign = true;
for(int j = 0; j <= n; j++) {
if(dcmp(A[i][j])) {
r2++;
if(j < n) r1++;
sign = false;
break;
}
}
if(sign) break;
}
if(r1 != r2) return -1;
if(r1 == r2 && r1 != n) return 0;
for(int i = n - 1; i >= 0; i--) {
A[i][n] /= A[i][i];
for(int j = i - 1; j >= 0; j--) A[j][n] -= A[i][n] * A[j][i];
}
return 1;
}
无脑式模板不解释→_→
然后用上面这个模板套了下这道模板题
#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck printf("fuck")
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MX = 3e5 + 5;
const double exps = 1e-8;
typedef vector<double> vec;
typedef vector<vec> mat;
int dcmp(double x) {
if(fabs(x) < exps) return 0;
return x < 0 ? -1 : 1;
}
int to_int(double x) {
return round(x);
}
void guass(mat &A, int m, int n) {
for(int i = 0; i < m; i++) {
int pv = i, id;
for(int j = 0; j <= n; j++) {
for(int k = i + 1; k < m; k++) {
if(fabs(A[k][j]) > fabs(A[pv][j])) {
pv = k;
}
}
if(dcmp(A[pv][j])) break;
}
swap(A[i], A[pv]);
for(id = 0; id <= n && !dcmp(A[i][id]); id++);
if(id > n) return;
for(int j = i + 1; j < m; j++) {
if(!dcmp(A[j][id])) continue;
double f = A[j][id] / A[i][id];
for(int k = id + 1; k <= n; k++) A[j][k] -= A[i][k] * f;
A[j][id] = 0;
}
}
}
/*
A是增广矩阵
n表示未知数个数,下标从0开始,下标n中的表示等号右边
-1表示无解,0表示多组解,1表示唯一一组解
如果是唯一解,会保存在A[i][n]中
*/
int solve(mat &A) {
int m = A.size(), n = A[0].size() - 1;
guass(A, m, n);
int r1 = 0, r2 = 0;
for(int i = 0; i < m; i++) {
bool sign = true;
for(int j = 0; j <= n; j++) {
if(dcmp(A[i][j])) {
r2++;
if(j < n) r1++;
sign = false;
break;
}
}
if(sign) break;
}
if(r1 != r2) return -1;
if(r1 == r2 && r1 != n) return 0;
for(int i = n - 1; i >= 0; i--) {
A[i][n] /= A[i][i];
for(int j = i - 1; j >= 0; j--) A[j][n] -= A[i][n] * A[j][i];
}
return 1;
}
int main() {
int n, m; //FIN;
while(~scanf("%d%d", &n, &m)) {
mat A(m, vec(n + 1));
for(int i = 0; i < m; i++) {
for(int j = 0; j <= n; j++) {
scanf("%lf", &A[i][j]);
}
}
int ret = solve(A);
if(ret < 0) printf("No solutions\n");
else if(ret == 0) printf("Many solutions\n");
else for(int i = 0; i < n; i++) {
printf("%d\n", to_int(A[i][n]));
}
}
return 0;
}