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 }