原题链接:https://www.acwing.com/activity/content/11
敲代码的注意事项:
1.for循环中的”++”和”- -“符号要应情况而选择,否则及容易打错,进而出现一些非常难找到的bug
2.doule和int的类型需要注意,例如输入输出过程,和定义过程
3.return的类型
代码:
#include<iostream> #include<algorithm> #include<cmath> using namespace std; const int N=110; const double egs=1e-6; double a[N][N]; int n; int gause() { int r,c;//r表示当前所在的行数,c表示当前所指向的列数 for(r=0,c=0;c<n;c++)//进行n次循环,将矩阵化为三角的形式 { int t=r; for(int i=r;i<n;i++) if(fabs(a[t][c])<fabs(a[i][c])) t=i; //寻找最大的数值是因为可以避免系数变得太大,精度较高. if(fabs(a[t][c])<egs) continue;//如果最大值是零,便可以直接跳过了 //之所以要小于1e-6,是因为c++浮点数的一种弊端,所以小于egs时,可以近似的看作是0 for(int i=c;i<=n;i++) swap(a[t][i],a[r][i]); //寻找到之后进行交换操作 for(int i=n;i>=c;i--) a[r][i]/=a[r][c]; //将当前第c位的值初始化为1,当然其他数也同样需要除以第c位,之所以从第n位开始,是为了不覆盖掉第c位的值 for(int i=r+1;i<n;i++) if(fabs(a[i][c])>egs)//如果当前行数为零,说明不用进行削为零的操作 for(int j=n;j>=c;j--) a[i][j]-=a[i][c]*a[r][j]; r++; } if(r<n) { for(int i=r;i<n;i++) if(a[i][n]>egs) return 2;//无解 /* 如果当前列的绝对值最大的值是0,那么r还继续停留,不转到下一行,但c却转至下一行, 由于循环过程中会进行消元操作,所以循环到该列时,下面所有行的c列就会被消成零. 假设该列只有零的情况出现一次的话,那么r最终会循环到n-2行,而c却循环到了第n-1列, 因为循环过程中的消元,所以第n-1行的所有数都会被消成零.如果此时d不为零的话,矛盾,无解; 如果为零的话,那么就会有无数组解.一列都是零的情况出现两次,三次,甚至更多次都是同理. */ return 1;//无数解 } //将未知数求解出来 for(int i=n-1;i>=0;i--)//i,j表示'行'的同时也表示'列' for(int j=i+1;j<n;j++) a[i][n]-=a[j][n]*a[i][j]; return 0;//有唯一解 } int main() { cin>>n; for(int i=0;i<n;i++) for(int j=0;j<=n;j++) scanf("%lf",&a[i][j]); int t=gause(); if(t==0) { for(int i=0;i<n;i++) printf("%.2lf\n",a[i][n]); } else if(t==1) printf("Infinite group solutions"); else printf("No solution"); return 0; }