高斯消元问题通常用来对线性方程组的求解
根据线性代数中所学,线性方程通常可表示成
a[i][0]*x0 + a[i][1]*x1 +a [i][2]*x2 ... + a[i][n-1]*xn-1 = b[i]
0<=i<n
这样就可以得到一个由n个线性方程组成方程组
我们通常将a[][]放入数组中的对应位置,b[] 作为一整列插入到a数组的最后一排
不断通过对行进行操作
比如 ri - k*rj , 用第i行的元素每一个都减去第j行对应列的元素的k倍,我们总是希望能够通过这个操作不断将矩阵朝着除去 b[]后的上三角
矩阵化简,就是令下三角矩阵均为0
那么就是不断从第一列开始不断将需要化简为0的项转化为0即可
那么我们就可以利用回代的方法,先算出最后一项x,然后不断往前递推,在第i行得到x[i]
当然这是最好的情况,解决线性方程组往往给的方程的数量和对应x的变量数量不一定相同
我令方程数量为equ , 变量数量为 var , 那么如果equ < var 的时候必然是有解的
因为至少有 var-equ+1个自由变量
因为每一行都会解决至多一个自由变量,当然如果某一行和前面的一行 的系数都存在倍数关系 exp: ai = k*aj
那么那一行其实效果是没有的,这个时候就一个自由变量都没有解决了
另外如果在化简矩阵的过程中某一行出现了(0,0,0,0....,0,b[i])(b[i] != 0)的情况那么就说明是不存在解的
所以对于我们来说,只要除去那些有相同效果的方程,剩下的方程组含有的方程为equ,那么
自由变量的个数就是 var - equ + 1 , 当自由变量个数大于1的时候我们就可以认为是有无穷多个解的
我们利用这个思想解决计算机上的问题时,可以套用如下模版:
1 int gcd(int a , int b) 2 { 3 if(b == 0) return a; 4 else return gcd(b , a%b); 5 } 6 7 int lcm(int a , int b) 8 { 9 return a/gcd(a , b)*b;//先除后乘防止溢出 10 } 11 12 inline int my_abs(int x) 13 { 14 return x>=0?x:-x; 15 } 16 17 inline void my_swap(int &a , int &b) 18 { 19 int tmp = a; 20 a = b , b = tmp; 21 } 22 /* 23 高斯消元解线性方程组的解 24 返回-2表示有浮点数的解,但无整数解 25 返回-1表示无解 26 返回0表示唯一解 27 大于0,表示无穷解,返回的是自由变元个数 28 有equ个方程,var个变元。增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var 29 总是考虑上三角部分,所以内部更新总是只更新了上三角部分 30 */ 31 int gauss(int equ , int var) 32 { 33 int max_r; // 当前这列绝对值最大的行 34 int col; // 当前处理的列 35 int ta , tb , i , j , k; 36 int Lcm , tmp , free_x_num , free_index; 37 38 for(i=0 ; i<=var ; i++) 39 x[i] = 0 , free_x[i] = true; 40 41 //转化为阶梯形矩阵 42 col = 0;//一开始处理到第0列 43 for(k=0 ; k<equ && col < var; k++,col++){ 44 /* 45 枚举当前处理的行 46 找到该行col列元素绝对值最大的那行与第k行交换, 47 这样进行除法运算的时候就可以避免小数除以大数了 48 */ 49 max_r = k; 50 for(i = k+1 ; i<equ ; i++) 51 if(my_abs(a[i][col]) > my_abs(a[max_r][col])) 52 max_r = i; 53 if(max_r != k){ 54 //交换两行的数据 55 for(i=k ; i<var+1 ; i++) 56 my_swap(a[max_r][i] , a[k][i]); 57 } 58 59 if(a[k][col] == 0){ 60 //说明该col列第k行以下全是0了,则处理当前行的下一列 61 k--; 62 continue; 63 } 64 65 for(i=k+1 ; i<equ ; i++){ 66 //枚举要删去的行 67 if(a[i][col] != 0 ){ 68 Lcm = lcm(my_abs(a[i][col]) , my_abs(a[k][col])); 69 ta = Lcm / my_abs(a[i][col]); 70 tb = Lcm / my_abs(a[k][col]); 71 if(a[i][col] * a[k][col] < 0) tb = -tb;//异号相加 72 for(j = col ; j<var+1 ; j++) 73 a[i][j] = a[i][j]*ta - a[k][j]*tb ; 74 } 75 } 76 } 77 78 //1.无解的情况 79 for(i=k ; i<equ ; i++){ 80 if(a[i][col] != 0) return -1; 81 } 82 83 //2.无穷解:在var*(var+1) 的增广阵中出现了(0,0,0....,0)这样的行,也即说明没有出现严格的上三角 84 //出现这样情况的行数也就是自由变元的个数 85 if(k < var){ 86 //首先初始化自由变元有var-k个,即不确定的变元至少有var-k个 87 for(i=k-1 ; i>=0 ; i--){ 88 //第i行一定不会是(0,0,0,...,0)的情况,因为这样的行实在第k行到equ行 89 //同样,第 i 行一定不会是(0,0 ... , a) , a != 0的情况 90 91 free_x_num = 0; 92 //free_x_num记录自由变元个数,如果超过1个,则解集无穷,无法求解. 93 94 for(j=0 ; j<var ; j++){ 95 if(a[i][j] != 0 && free_x[j]) free_x_num++ , free_index = j; 96 } 97 98 if(free_x_num > 1) continue; //无法求解出确定变元 99 100 tmp = a[i][var]; 101 for(j=0 ; j<var ; j++) 102 if(a[i][j] != 0 && j != free_index) 103 tmp -= a[i][j]*x[j]; 104 x[free_index] = tmp / a[i][free_index];//求出该变元 105 free_x[free_index] = false;//该变元确定 106 } 107 return var - k;//自由变元有var-k个 108 } 109 110 //唯一解的情况:在var*(var+1) 的增广矩阵中形成严格的上三角阵 111 //计算x[n-1] , x[n-2] .... x[0] 回代计算,先得到后面的值,推到前面的值 112 for(int i=var-1 ; i>=0 ; i--){ 113 tmp = a[i][var]; 114 for(int j=i+1 ; j<var ; j++){ 115 if(a[i][j] != 0 ) tmp -= a[i][j]*x[j]; 116 } 117 // if(tmp % a[i][i] != 0) return -2; //说明浮点数存在,无整数解,但是有小数解 118 x[i] = tmp / a[i][i]; 119 } 120 return 0; 121 }
我还在坚持,我还未达到我所想,梦~~一直在