zoukankan      html  css  js  c++  java
  • 高斯消元法模板

      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 }
    View Code

  • 相关阅读:
    发送http请求时,如果token过期了会返回什么
    遍历某个文件夹下所有的文件
    写出冒泡排序的算法
    sql,学生表(student),id,name ,age ,求前10个年龄最大的
    给一个无序数组,输出这个数组的前n个最大的
    python随机数模块random
    java --String、StringBuffer、StringBuilder
    java内存空间
    第四次寒假作业
    寒假作业3
  • 原文地址:https://www.cnblogs.com/dilthey/p/7120865.html
Copyright © 2011-2022 走看看