高斯消元

来源:互联网 发布:手机音乐闪光灯软件 编辑:程序博客网 时间:2024/06/18 05:54

发现有些题目与高斯消元有关,硬着头皮学了学,先把模板整理下

一号模板,基本操作

代码:

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int maxn=105;int equ,xsum;//行数为equ,表示方程的个数,xsum表示变元个数int a[maxn][maxn];int x[maxn];//解集,储存解bool freeX[maxn];//判断是否是不确定的变元,1为不确定变元,一开始全为不确定变元int free_num;void debug()//找bug{    int i,j;    for(i=0;i<equ;i++){        for(j=0;j<xsum+1;j++)        cout<<a[i][j]<<" ";        cout<<endl;    }    cout<<endl;}inline int gcd(int a,int b)//求最大公约数{    if(b==0) return a;    return gcd(b,a%b);}inline int lcm(int a,int b)//求最小公倍数{    return a*b/gcd(a,b);}//高斯消元法解方程组(-2表示有浮点数解,但无整数解,-1表示无解,0表示唯一解,//大于0表示无穷解,并返回自由变元的个数)int Gauss()//高斯消元法{    int i,j,k;    int max_r;//表示这列绝对值最大的行。    int col;//当前处理列    int ta,tb;    int LCM;    int free_x_num,free_index;    //转化为阶梯阵    col=0;//当前处理的列    for(k=0;k<equ&&col<xsum;k++,col++){        //枚举当前处理的行。        //找到该col列元素绝对值最大的哪行与第k行交换。为了减小误差        max_r=k;        for(i=k+1;i<equ;i++)            if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;        if(max_r!=k)            for(j=k;j<xsum+1;j++) swap(a[k][j],a[max_r][j]);//max_r与第k行进行交换        if(a[k][col]==0){//说明该col列第k行一下全是0了,则处理当前的下一列            k--;            continue;        }        for(i=k+1;i<equ;i++){            //枚举要删去的行            if(a[i][col]!=0){                LCM=lcm(abs(a[i][col]),abs(a[k][col]));                ta=LCM/abs(a[i][col]),tb=LCM/abs(a[k][col]);                if(a[i][col]*a[k][col]<0) tb=-tb;//异号的时候是两数想加                for(j=col;j<xsum+1;j++)                    a[i][j]=a[i][j]*ta-a[k][j]*tb;            }        }    }    debug();    //无解的情况    for(i=k;i<equ;i++)        if(a[i][col]!=0) return -1;    //无穷解的情况    if(k<xsum){        //首先自由变量有var-k个,即不确定的变元至少有var-k个        for(i=k-1;i>=0;i--){            //第i行一定不会是(0,0,。。。。0)的情况,因为这样的行是在第k行到第equ行。            //可能会出现无解的情况            free_x_num=0;//用于判断该行中的不确定变元的个数,如果超过一个则无法求解,他们仍然为不确定的变元            for(j=0;j<xsum;j++)                if(a[i][j]!=0&&freeX[j]) free_x_num++,free_index=j;            if(free_x_num>1) continue;//无法求解出该变元            //如果只有一个变元free——index,南无就可以求出            int temp=a[i][xsum];            for(j=0;j<xsum;j++)                if(a[i][j]!=0&&j!=free_index) temp-=a[i][j]*x[j];            x[free_index] = temp/a[i][free_index];//求出该变元            freeX[free_index]=0;//该变元是确定的        }        return xsum-k;//自由变元有xsum-k个    }    //计算出有唯一解的情况在xsum * (xsum + 1)的增广阵中形成严格的上三角阵    //计算出Xn-1,Xn-2。。。。    for(i=xsum-1;i>=0;i--){        int temp=a[i][xsum];        for(j=i+1;j<xsum;j++)            if(a[i][j]!=0) temp-=a[i][j]*x[j];        if(temp%a[i][j]!=0) return -2;//有浮点数解,但无整数解        x[i]=temp/a[i][i];    }    return 0;}int main(){    int i,j;    while(scanf("%d %d",&equ,&xsum)!=EOF){        memset(a,0,sizeof(a));        memset(x,0,sizeof(x));        memset(freeX,true,sizeof(freeX));        for(i=0;i<equ;i++){            for(j=0;j<xsum+1;j++)                scanf("%d",&a[i][j]);        }        debug();        free_num=Gauss();        if(free_num==-1) printf("wujie\n");        else if(free_num==-2) printf("有浮点数解无整数解");        else if(free_num>0){            printf("有无穷多的解!自由变元的个数%d\n",free_num);            for(i=0;i<xsum;i++){                if(freeX[i]) printf("x%d是不确定的\n",i+1);                else printf("x%d:%d\n",i+1,x[i]);            }        }        else            for(i=0;i<xsum;i++) printf("x%d:%d\n",i+1,x[i]);    }    return 0;}





1 0