高斯消元法模板_i++高斯消元法模板_模板_02


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("\n");
21 for(i=0;i<equ;i++)
22 {
23 for(j=0;j<var+1;j++) printf("%d ",a[i][j]);
24 printf("\n");
25 }
26 printf("\n");
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("无解.\n");
134 else if(free_num==-2) printf("有浮点数解,无整数解.\n");
135 else if(free_num>0)
136 {
137 printf("无穷多解, 自由变元个数为%d\n.", free_num);
138 for(i=0;i<var;i++)
139 {
140 if(free_x[i]) printf("x%d 是不确定的.\n",i+1);
141 else printf("x%d: %d\n",i+1,x[i]);
142 }
143 }
144 else
145 {
146 for(i=0;i<var;i++) printf("x%d: %d\n",i+1,x[i]);
147 }
148 printf("\n");
149 }
150 return 0;
151 }

View Code

高斯消元法模板_i++_03

 ​