高斯消元法模板

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<string.h>
  5 #include<math.h>
  6 using namespace std;
  7 
  8 const int MAXN=50;
  9 
 10 
 11 
 12 int a[MAXN][MAXN];//增广矩阵
 13 int x[MAXN];//解集
 14 bool free_x[MAXN];//标记是否是不确定的变元
 15 
 16 
 17 void Debug(int equ,int var)
 18 {
 19     int i,j;
 20     printf("
");
 21     for(i=0;i<equ;i++)
 22     {
 23         for(j=0;j<var+1;j++) printf("%d ",a[i][j]);
 24         printf("
");
 25     }
 26     printf("
");
 27 }
 28 
 29 
 30 inline int gcd(int m,int n){return n?gcd(n,m%n):m;}
 31 inline int lcm(int a,int b){return a/gcd(a,b)*b;}
 32 
 33 
 34 //高斯消元法解方程组(Gauss elimination).
 35 //有equ个方程,var个变元。增广矩阵:行数为equ,分别为0到equ-1;列数为var+1,分别为0到var-1以及var.
 36 //该函数返回:-2表示有浮点数解,但无整数解;-1表示无解;0表示唯一解;大于0表示有无穷多解,返回自由变元的个数.
 37 int Gauss_eli(int equ,int var)
 38 {
 39     int i,j,k;
 40     int max_r;    //当前这列绝对值最大的行.
 41     int col;    //当前处理的列.
 42     int ta,tb;
 43     int LCM;
 44     int temp;
 45     int free_x_num;
 46     int free_index;
 47 
 48     for(int i=0;i<=var;i++)//初始化 
 49     {
 50         x[i]=0;
 51         free_x[i]=1;
 52     }
 53     for(k=0,col=0; k<equ && col<var; k++,col++)//转换为阶梯阵.
 54     {
 55         max_r=k;
 56         for(i=k+1;i<equ;i++) if( abs(a[i][col]) > abs(a[max_r][col]) ) max_r=i;
 57         if(max_r!=k)
 58         {
 59             for(j=k;j<var+1;j++) swap(a[k][j],a[max_r][j]);
 60         }
 61         //找到该col列元素绝对值最大的那行与第k行交换(为了在除法时减小误差).
 62         
 63         
 64         if(a[k][col]==0)//若绝对值最大的是0,则该col列第k行以下全是0,则处理当前行的下一列.
 65         {
 66             k--;
 67             continue;
 68         }
 69         
 70         for(i=k+1;i<equ;i++)//枚举要消去的行.
 71         {
 72             if(a[i][col]!=0)
 73             {
 74                 LCM = lcm( abs(a[i][col]) , abs(a[k][col]) );
 75                 ta = LCM/abs(a[i][col]);
 76                 tb = LCM/abs(a[k][col]);
 77                 if(a[i][col]*a[k][col]<0) tb=-tb;//异号的情况是相加.
 78                 for(j=col;j<var+1;j++) a[i][j] = a[i][j]*ta - a[k][j]*tb;//进行消元.
 79             }
 80         }
 81     }
 82 
 83     Debug(equ,var);
 84 
 85     //1.无解的情况: 化简的增广阵中存在(0, 0, ..., a)这样的行(a != 0).
 86     for (i=k;i<equ;i++) if(a[i][col]!=0) return -1;
 87     
 88     //2.无穷解的情况: 在 var*(var+1) 的增广阵中出现(0, 0, ..., 0)这样的行,即说明没有形成严格的上三角阵.
 89     //并且出现的行数即为自由变元的个数.
 90     if(var>k)
 91     {
 92         //首先,自由变元有 var - k 个,即不确定的变元至少有 var - k 个.
 93         for(i=k-1;i>=0;i--)
 94         {
 95             //第i行一定不会是(0, 0, ..., 0)的情况,因为这样的行是在第k行到第equ行.
 96             //同样,第i行一定不会是(0, 0, ..., a), a != 0的情况,这样的无解的.
 97             free_x_num=0;    //用于判断该行中的不确定的变元的个数,如果超过1个,则无法求解,它们仍然为不确定的变元.
 98             for(j=0;j<var;j++) if(a[i][j] != 0 && free_x[j]) free_x_num++ , free_index=j;
 99             if(free_x_num>1) continue;    //无法求解出确定的变元.
100             
101             //若只有一个不确定的变元free_index,那么可以求解出该变元.
102             temp=a[i][var];
103             for(j=0;j<var;j++) if(a[i][j] != 0 && j != free_index) temp-=a[i][j]*x[j];
104             x[free_index]=temp/a[i][free_index];    //求出该变元.
105             free_x[free_index]=0;    //该变元是确定的.
106         }
107         return var-k; //自由变元有 var - k 个.
108     }
109     
110     //3.唯一解的情况: 在 var*(var+1) 的增广阵中形成严格的上三角阵.
111     //计算出x[n-1], x[n-2] ... X[0].
112     for(i=var-1;i>=0;i--)
113     {
114         temp=a[i][var];
115         for(j=i+1;j<var;j++) if(a[i][j]!=0) temp-=a[i][j]*x[j];
116         if(temp%a[i][i]!=0) return -2; // 说明有浮点数解,但无整数解.
117         x[i]=temp/a[i][i];
118     }
119     return 0;
120 }
121 
122 int main()
123 {
124     int i, j;
125     int equ,var;
126     while(scanf("%d%d",&equ,&var)!=EOF)
127     {
128         memset(a,0,sizeof(a));
129         for(i=0;i<equ;i++) for(j=0;j<var+1;j++) scanf("%d", &a[i][j]);
130         //Debug(equ,var);
131         
132         int free_num=Gauss_eli(equ,var);
133         if(free_num==-1) printf("无解.
");
134         else if(free_num==-2) printf("有浮点数解,无整数解.
");
135         else if(free_num>0)
136         {
137             printf("无穷多解, 自由变元个数为%d
.", free_num);
138             for(i=0;i<var;i++)
139             {
140                 if(free_x[i]) printf("x%d 是不确定的.
",i+1);
141                 else printf("x%d: %d
",i+1,x[i]);
142             }
143         }
144         else
145         {
146             for(i=0;i<var;i++) printf("x%d: %d
",i+1,x[i]);
147         }
148         printf("
");
149     }
150     return 0;
151 }
View Code

原文地址:https://www.cnblogs.com/dilthey/p/7120865.html