高斯消元

高斯消元用来解线性方程组,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 }
View Code

我愿称之为扩展高斯消元

附一道板子题,高级版的 线性方程组

posted @ 2021-05-13 13:52  D'A'T  阅读(68)  评论(0)    收藏  举报