Gauss 消元(模板)

Posted hk lin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gauss 消元(模板)相关的知识,希望对你有一定的参考价值。

  1 /* 
  2     title:Gauss消元整数解/小数解整数矩阵模板 
  3     author:lhk
  4     time: 2016.9.11
  5     没学vim的菜鸡自己手打了     
  6 */
  7 #include<cstdio>
  8 #include<iostream>
  9 #include<cstring>
 10 #include<algorithm>
 11 #include<cmath>
 12 #define clr(x) memset(x,0,sizeof(x))
 13 #define clrdown(x) memset(x,-1,sizeof(x))
 14 #define maxn 910
 15 #define maxm 910 
 16 #define mod 3 
 17 using namespace std;
 18 int A[maxn][maxm];//Gauss消元的增广矩阵 
 19 int free_x[maxm];//自由变元的位置 
 20 int x[maxm];//整数解集 
 21 double xd[maxm];//小数解集 
 22 void init(int n,int m);//矩阵初始化操作 
 23 int gauss(int n,int m);//gauss消元部分 
 24 void print(int n);//输出解集 
 25 int exgcd(int a,int b,int &x,int &y);//扩展欧几里得求逆元,对于模mod的矩阵除法需要 
 26 int lcm(int a,int b);
 27 int gcd(int a,int b);
 28 int main()
 29 {
 30     int T,n,m; 
 31     scanf("%d",&T);
 32     while(T--)
 33     {
 34         scanf("%d%d",&n,&m);
 35         init(n,m);
 36         int p=gauss(n,m); 
 37         if(p==-1)
 38         {
 39             printf("no answer\n");
 40             return 0; 
 41          } 
 42         if(p==-2)
 43         { 
 44                printf("have float answer\n");
 45             return 0; 
 46         }
 47         printf("the num of free_x is %d\n",p);
 48         print(m);
 49     }
 50     return 0;
 51 }
 52 //输出解的和,自由变元数量以及各个解 
 53 void print(int n)
 54 {
 55     //    若有小数解换为xd输出 
 56     int sum=0;
 57     for(int i=0;i<n;i++)
 58         sum+=x[i];
 59     printf("sum=%d\n",sum); 
 60     for(int i=0;i<n;i++)
 61         printf("x%d=%d\n",i+1,x[i]);
 62     return ;
 63 }
 64 //读入增广矩阵 
 65 void init(int n,int m)
 66 {
 67     clr(A);
 68     for(int i=0;i<n;i++)
 69         for(int j=0;j<=m;j++)
 70         scanf("%d",&A[i][j]); 
 71     clrdown(x);
 72     clr(free_x);
 73     return ;
 74 }
 75 int gauss(int n,int m)//输出-1是无解,-2是有小数解,>=0则是自由变元的数量和全为整数解 
 76 {
 77     int k,col,num=0,max_r,dou,max_x,LCM,ta,tb;
 78 //k为当前操作行,col为操作主元素所在列 
 79     for(k=0,col=0;k<n && col<m;k++,col++)
 80     {
 81         //若A[K][col]不为col列最大,则将k行与k+1到n-1行中A[i][col]绝对值最大的行交换
 82         max_r=k;
 83         max_x=abs(A[k][col]);
 84         for(int i=k+1;i<n;i++)
 85             if(max_x<abs(A[i][col]))
 86             {
 87                 max_x=abs(A[i][col]);
 88                 max_r=i;
 89             }
 90         if(max_r!=k)
 91         {
 92             for(int j=col;j<=m;j++)
 93                 swap(A[k][j],A[max_r][j]);
 94         }
 95         //若k到n-1行A[i][col]全为0,则主元素指向当前行下一列的元素 
 96         if(A[k][col]==0)
 97         {
 98             k--;
 99             free_x[num++]=col;
100             //自由变元为当前col 
101             continue;
102         }
103         for(int i=k+1;i<n;i++)
104         if(A[i][col])
105         {
106             LCM=lcm(abs(A[k][col]),abs(A[i][col]));
107             ta=LCM/abs(A[i][col]);
108             tb=LCM/abs(A[k][col]);
109             if(A[k][col]*A[i][col]<0) tb=-tb;//若符号不同则取反 
110             for(int j=col;j<=m;j++)
111             {
112                     A[i][j]=A[i][j]*ta-A[k][j]*tb;
113                  // A[i][j]=((A[i][j]*ta-A[k][j]*tb)%mod+mod)%mod; //模mod矩阵的消元 
114             }
115         }
116     }
117     //k行及之后若有(0,0,0……,0,a)(a!=0)的行,则无解输出-1 
118     for(int i=k;i<n;i++)
119         if(A[i][col]!=0)
120             return -1;    
121     int temp;
122     //对自由变元的赋值,可有多种方式 
123     //若为小数解则换为xd; 
124     for(int i=0;i<num;i++)
125         x[free_x[i]]=0;
126     //int  xi,yi; exgcd需要 
127     for(int i=k-1,c=m-1;i>=0;c=m-1,i--)
128     {
129         temp=A[i][m];
130         while(x[c]!=-1)
131         {
132             if(A[i][c])
133                  temp-=x[c]*A[i][c]; 
134                 //temp=((temp-(x[c]*A[i][c])%mod)%mod+mod)%mod;//模mod矩阵的回代  
135             c--;
136         }
137         if(temp%A[i][c]!=0) return -2;
138         x[c]=temp/A[i][c]; 
139         /*exgcd(A[i][c],mod,xi,yi);
140         xi=(xi%mod+mod)%mod;
141         x[c]=(temp*xi%mod+mod)%mod;*/ //模mod 矩阵的x[i]的赋值 
142     }
143     return col-k;
144 }
145 int exgcd(int a,int b,int &x,int &y)
146 {
147     if(b==0)
148     {
149         x=1;
150         y=0;
151         return a;
152     }
153     else
154     {
155         int r=exgcd(b,a%b,y,x);
156         y-=x*(a/b);
157         return r;
158     }
159 }
160 int gcd(int a,int b)
161 {
162     int c;
163     while(b!=0)
164     {
165         c=a%b;
166         a=b;
167         b=c;
168     }
169     return a;
170 }
171 int lcm(int a,int b)
172 {
173     return a/gcd(a,b)*b;
174 }

 

以上是关于Gauss 消元(模板)的主要内容,如果未能解决你的问题,请参考以下文章

高斯消元法(Gauss Elimination)超详解&模板

POJ1830开关问题——gauss消元

模板高斯消元

(Gauss-Jordan)高斯消元法求逆矩阵(含C/C++实现代码)

P3389 模板高斯消元法

hdu 5755(GAuss 消元)