zoukankan      html  css  js  c++  java
  • 高斯消元模板(转)

    参考资料:http://blog.sina.com.cn/s/blog_afe6bb330101a59d.html

    模板:

    const int maxn=30;
    int a[maxn][maxn+1],x[maxn];//a是系数矩阵和增广矩阵,x是最后存放的解
    
    // a[][maxn]中存放的是方程右面的值(bi)
    
    int equ,var;//equ是系数阵的行数,var是系数矩阵的列数(变量的个数)
    
    int free_num,ans=100000000;
    
    void Debug(void)  //调试输出,看消元后的矩阵值,提交时,就不用了
    {
        int i, j;
        for (i = 0; i < equ; i++)
        {
            for (j = 0; j < var + 1; j++)
            {
                cout << a[i][j] << " ";
            }
            cout << endl;
        }
        cout << endl;
    }
    inline int gcd(int a, int b) //最大公约数
    {
        int t;
        while (b != 0)
        {
            t = b;
            b = a % b;
            a = t;
        }
        return a;
    }
    inline int lcm(int a, int b)  //最小公倍数
    {
        return a  / gcd(a, b)*b;
    }
    
    void swap(int &a,int &b)
    {
        int temp=a;    //交换2个数
        a=b;
        b=temp;
    }
    
    int Gauss()
    {
        int k,col = 0;  //当前处理的列
        for(k = 0; k < equ && col < var; ++k,++col)
        {
            int max_r = k;
            for(int i = k+1; i < equ; ++i)
                if(a[i][col] > a[max_r][col])
                    max_r = i;
            if(max_r != k)
            {
                for(int i = k; i < var + 1; ++i)
                    swap(a[k][i],a[max_r][i]);
            }
            if(a[k][col] == 0)
            {
                k--;
                continue;
            }
            for(int i = k+1; i < equ; ++i)
            {
                if(a[i][col] != 0)
                {
                    int LCM = lcm(a[i][col],a[k][col]);
                    int ta = LCM/a[i][col], tb = LCM/a[k][col];
                    if(a[i][col]*a[k][col] < 0)
                        tb = -tb;
                    for(int j = col; j < var + 1; ++j)
                        a[i][j] = ( (a[i][j]*ta)%2 - (a[k][j]*tb)%2  +  2 ) % 2;    //a[i][j]只有0和1两种状态
                }
            }
        }
        //上述代码是消元的过程,行消元完成
        //解下来2行,判断是否无解
        //注意K的值,k代表系数矩阵值都为0的那些行的第1行
        for(int i = k; i < equ; ++i)
            if(a[i][col] != 0)
                return -1;   // 无解返回 -1
        //Debug();
        //唯一解或者无穷解,k<=var
        //var-k==0  唯一解;var-k>0 无穷多解,自由解的个数=var-k
        //能执行到这,说明肯定有解了,无非是1个和无穷解的问题。
        //下面这几行很重要,保证秩内每行主元非0,且按对角线顺序排列,就是检查列
        for(int i = 0; i <equ; i++)
            if(!a[i][i])
            {
                int j;
                for(j=i+1;j<=var;j++)
                    if(a[i][j])
                        break;
                if(j == var)
                    break;
                for(int k = 0; k < equ; ++k)
                    swap(a[k][i],a[k][j]);
            }
        // ----处理保证对角线主元非0且顺序,检查列完成
        // free_num=k;
        if (var-k>0)
        {
         //无穷多解,先枚举解,然后用下面的回带代码进行回带;
         //这里省略了下面的回带的代码;不管唯一解和无穷解都可以回带,只不过无穷解//回带时,默认为最后几个自由变元=0而已。
        }
        if (var-k==0)//唯一解时
        {
            //下面是回带求解代码,当无穷多解时,最后几行为0的解默认为0;
            for(int i = k-1; i >= 0; --i) //从消完元矩阵的主对角线非0的最后1行,开始往//回带
            {
                int tmp = a[i][var] % 2;
                for(int j = i+1; j < var; ++j) //x[i]取决于x[i+1]--x[var]啊,所以后面的解对前面的解有影响。
                    if(a[i][j] != 0)
                        tmp = ( tmp - (a[i][j]*x[j])%2  +  2 ) % 2;
                //if (a[i][i]==0) x[i]=tmp;   //最后的空行时,即无穷解得
                //else
                x[i] = (tmp/a[i][i]) % 2; //上面的正常解
            }
            //回带结束了
        }
    }
  • 相关阅读:
    神秘现象?多种情况比较
    [备忘]C++BUILDER的文件操作
    缘起
    [备忘]一个二维数组的冒泡排序
    无可救药地买入NDSL
    递归的实质
    [网游计划第九、十天]能力有限,做些小品
    大学有救
    struts2+convertion实现struts.xml的零配置
    BSD下的超级终端
  • 原文地址:https://www.cnblogs.com/oneshot/p/3997335.html
Copyright © 2011-2022 走看看