传送门:点击打开链接
思路:高斯消元。。
没学线代前看了好久的高斯消元都没看懂,感觉线代书里的高斯消元讲的详细多了。。
然后网上找过关于高斯消元的代码,几乎没有能返回是否有解,有几组解等的代码-_-
然后今天写了一天,也总算完成了
大概的思路也就是做出梯形矩阵,然后判断矩阵的秩,详细推荐参考线性代数的书会比较好
如果不想弄懂也行,,反正模板已弄好了,以后可以直接套模板
下面是模板
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; }