高斯消元
高斯消元用来解线性方程组,n个方程n个未知数可以分别解出来并给出解的情况
1.用矩阵表示方程组
2.通过初等行变换变成上三角方程组
3.依次回代解出每个元
回代的时候有一种高斯——约旦消元,把元都放在对角线上
保证有解时的简单版
1 for(int i=1;i<=n;i++) 2 { 3 if(pd(a[i][i],0)) 4 { 5 int j=i+1; 6 while(pd(a[j][i],0))j++; 7 for(int k=i;k<=n;k++) 8 swap(a[i][k],a[j][k]); 9 swap(b[i],b[j]) 10 } 11 for(int j=i+1;j<=n;j++) 12 { 13 double p=a[j][i]/a[i][i]; 14 for(int k=i;k<=n;k++) 15 a[j][k]-=p*a[i][k]; 16 b[j]-=p*b[i]; 17 } 18 } 19 for(int i=n;i>=1;i--) 20 { 21 for(int j=n-i;j>=1;j--) 22 b[i]-=a[i][n-j+1]*c[n-j+1]; 23 c[i]=b[i]/a[i][i]; 24 }
如果让解系数为浮点数的线性方程组(期望dp的一种情况)的时候要注意精度,最好把每一列最大的数作为主元
在上面的基础上改一点点
1 for(int i=1;i<=n;i++) 2 { 3 double p=abs(a[i][i]); 4 int p=i; 5 for(int j=i+1;j<=n;j++) 6 if(abs(a[j][i])>p) 7 { 8 p=abs(a[j][i]);pp=j;//注意这里要用绝对值 9 } 10 for(int k=i;k<=n;k++)swap(a[i][k],a[pp][k]); 11 swap(b[i],b[pp]); 12 for(int j=i+1;j<=n;j++) 13 { 14 double p=a[j][i]/a[i][i]; 15 for(int k=i;k<=n;k++) 16 a[j][k]-=p*a[i][k]; 17 b[j]-=p*b[i]; 18 } 19 } 20 for(int i=n;i>=1;i--) 21 { 22 for(int j=n-i;j>=1;j--) 23 b[i]-=a[i][n-j+1]*c[n-j+1]; 24 c[i]=b[i]/a[i][i]; 25 }
如果题目让判断是否唯一解,把在j自加时加一个溢出特判就行
1 while(pd(a[j][i],0)) 2 { 3 if(j>=n) 4 { 5 cout<<"0";return 0; 6 } 7 j++; 8 }
如果要判断更具体多解还是无解,就引入一个新变量p,出来每行有效元个数递减,就好判断了
1 #include <bits/stdc++.h> 2 using namespace std; 3 double a[55][55],b[55],c[55]; 4 double exs=1e-8; 5 bool pd(double x,double y) 6 { 7 if(x<y)swap(x,y); 8 if((x-y)<exs)return 1; 9 return 0; 10 } 11 signed main() 12 { 13 int n; 14 cin>>n; 15 for(int i=1;i<=n;i++) 16 { 17 for(int j=1;j<=n;j++) 18 scanf("%lf",&a[i][j]); 19 scanf("%lf",&b[i]); 20 } 21 for(int i=1;i<=n;i++) 22 { 23 int p=i; 24 while(pd(a[i][p],0)) 25 { 26 if(p>n){ 27 i=n+1;break;//跳出所有循环 28 } 29 int j=i+1; 30 while(pd(a[j][p],0)&&j<=n)j++; 31 if(j>n){p++;continue;} 32 for(int k=p;k<=n;k++)swap(a[i][k],a[j][k]); 33 swap(b[i],b[j]); 34 } 35 for(int j=i+1;j<=n;j++) 36 { 37 double pp=a[j][p]/a[i][p]; 38 for(int k=p;k<=n;k++) 39 a[j][k]-=pp*a[i][k]; 40 b[j]-=pp*b[i]; 41 } 42 } 43 bool dj=0; 44 for(int i=n;i>=1;i--) 45 { 46 bool p=0; 47 for(int j=n;j>=1;j--) 48 if(a[i][j])p=1; 49 if(!p) 50 { 51 dj=1; 52 if(b[i]){cout<<-1;return 0;} 53 } 54 } 55 if(dj){cout<<0;return 0;} 56 for(int i=n;i>=1;i--) 57 { 58 for(int j=n-i;j>=1;j--) 59 b[i]-=a[i][n-j+1]*c[n-j+1]; 60 c[i]=b[i]/a[i][i]; 61 } 62 for(int i=1;i<=n;i++) 63 { 64 printf("x%d=",i); 65 if(pd(c[i],0))printf("0\n"); 66 else printf("%.2lf\n",c[i]); 67 } 68 return 0; 69 }
我愿称之为扩展高斯消元
附一道板子题,高级版的 线性方程组
予明日所有失败者 赋万千不灭颂歌

浙公网安备 33010602011771号