zoukankan      html  css  js  c++  java
  • 行列式计算(编程实现)

                                                           Write programs that do one thing and do it well

                                                                                         -----  Doug McIlroy (UNIX哲学)

    如果你学过线代, 又恰巧你是个coder, 那么你应该写个计算行列式的program。

    计算行列式(数学知识): 

                    每行都按行坐标排序, 求出列坐标排列的逆序数

                    根据逆序数的奇偶行判断该项的正负(奇负, 偶正)

                    逐项求和。

    说明: 输入行列式的 行(列)数 N

             并依次输入n*n个数。 程序将输出

             行列式的计算算式,并得出结果!

    代码实现分析: 调用头文件<algorithm>里的库函数 next_permutation()  具体实现细节详见代码。

                        用线段树求逆序数时间复杂度为N*logN。 当然以这种时间复杂度的算法还有树状数组求逆序数, 归并排序求逆序数。

                        当然你也可以用直接暴力的方法求出逆序数,代码是十分简单的。时间复杂度和插入排序相同n*n。

                        然后就是具体的一些实现细节啦

    线段树求逆序数, 代码有点长。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    void PushUp(int cur, int *sum)
    {
        sum[cur] = sum[cur<<1]+sum[cur<<1|1];
    }
    
    void Build(int l, int r, int cur, int *sum)
    {
        sum[cur] = 0;
        if(l==r) return ;
        int m = (l+r)>>1;
        Build(l, m, cur<<1, sum);
        Build(m+1, r, cur<<1|1, sum);
    }
    
    void Update(int p, int l, int r, int cur, int *sum)
    {
        if(l==r)
        {
            sum[cur]++;
            return;
        }
        int m = (l+r)>>1;
        if(p<=m) Update(p, l, m, cur<<1, sum);
        else Update(p, m+1, r, cur<<1|1, sum);
        PushUp(cur, sum);
    }
    int Query(int L, int R, int l, int r, int cur, int *sum)
    {
        if(L<=l&&r<=R)
        {
            return sum[cur];
        }
        int m = (l+r)>>1;
        int ret = 0;
        if(L<=m) ret+=Query(L, R, l, m, cur<<1, sum);
        if(R>m) ret+=Query(L, R, m+1, r, cur<<1|1, sum);
        return ret;
    }
    
    int Reverse(int n, int *p)
    {
        int sum[n<<2];
        Build(0, n-1, 1, sum);
        int tot = 0;
        for(int i=0; i<n; i++)
        {
            tot+=Query(p[i], n-1, 0, n-1, 1, sum);
            Update(p[i], 0, n-1, 1, sum);
        }
        return tot;
    }
    
    void solve(int n, int a[15][15])
    {
        int flag = 0; 
        long long ans=0;
        int p[15];
        for(int i=0; i<n; i++) 
        p[i] = i+1;
        do
        {
            int ok = Reverse(n, p);
            if(ok&1) 
            {
                flag++;
               printf(" - ");
                long long temp=1;
                for(int j=1, i=0; i<n; j++, i++)
                {
                    temp*=(long long)a[j][p[i]];
                    if(j!=1)printf(" * ");
                    printf("%d", a[j][p[i]]);
                    
                }
                ans-=temp;
            }
            else 
            {
               if(flag)printf(" + ");
               flag++;
                 long long temp=1;
                for(int j=1, i=0; i<n; j++, i++)
                {
                    temp*=(long long)a[j][p[i]];
                    if(j!=1)printf(" * ");
                    printf("%d", a[j][p[i]]);
                }
                ans+=temp;
            }
        }while(next_permutation(p, p+n));
        printf("
    %d
    
    ", ans);
    }
    
    int main() {
      int n;
      int a[15][15];
      while(scanf("%d", &n)!=EOF)
      {
          for(int i=1; i<=n; i++)
          for(int j=1; j<=n; j++)
          scanf("%d", &a[i][j]);
        solve(n, a);
      }
      return 0;
    }
    View Code


    归并排序求逆序数:

    归并排序

    void Merge_Sort(int * A, int x, int y, int *T)
    {
        if(y-x > 1) 
        {
            int m = x + (y-x)/2;
            int p = x, q = m, i = x;
            Merge_Sort(A, x, m, T);
            Merge_Sort(A, m, y, T);
            while(p < m || q < y)
            {
                if(q >= y ||(p<m && A[p] <= A[q])) T[i++] = A[p++];
                else    T[i++] = A[q++];
            } 
            for( i = x; i < y; i++) A[i] = T[i]; 
        }
    }            

    稍加改动, 即可求逆序数。 把 “else T[i++] = A[q++]; ” 改成 “else { T[i++] = A[q++]; cnt += m-p; }” 

    即:

    void Merge_Sort(int * A, int x, int y, int *T)
    {
        if(y-x > 1) 
        {
            int m = x + (y-x)/2;
            int p = x, q = m, i = x;
            Merge_Sort(A, x, m, T);
            Merge_Sort(A, m, y, T);
            while(p < m || q < y)
            {
                if(q >= y ||(p<m && A[p] <= A[q])) T[i++] = A[p++];
                else  {    T[i++] = A[q++]; cnt += m-p;}
            } 
            for( i = x; i < y; i++) A[i] = T[i]; 
        }
    }            


    如果想求顺序数的个数, 直接用总情况数 (n-1+1)*(n-1)/2   - 逆序数   即可!

    用归并排序法----计算行列式

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    
    int Merge_Sort(int * A, int x, int y)
    {
        int T[1000];
        int cnt = 0;
        if(y-x > 1) 
        {
            int m = x + (y-x)/2;
            int p = x, q = m, i = x;
            Merge_Sort(A, x, m);
            Merge_Sort(A, m, y);
            while(p < m || q < y)
            {
                if(q >= y ||(p<m && A[p] <= A[q])) T[i++] = A[p++];
                else  {    T[i++] = A[q++]; cnt += m-p;}
            } 
            
        }
        return cnt;
    }            
    
    void solve(int n, int a[15][15])
    {
        int flag = 0; 
        long long ans=0;
        int p[15];
        for(int i=0; i<n; i++) 
        p[i] = i+1;
        do
        {
            int ok = Merge_Sort(p, 0,  n); 
            if(ok&1) 
            {
                flag++;
               printf(" - ");
                long long temp=1;
                for(int j=1, i=0; i<n; j++, i++)
                {
                    temp*=(long long)a[j][p[i]];
                    if(j!=1)printf(" * ");
                    printf("%d", a[j][p[i]]);
                    
                }
                ans-=temp;
            }
            else 
            {
               if(flag)printf(" + ");
               flag++;
                 long long temp=1;
                for(int j=1, i=0; i<n; j++, i++)
                {
                    temp*=(long long)a[j][p[i]];
                    if(j!=1)printf(" * ");
                    printf("%d", a[j][p[i]]);
                }
                ans+=temp;
            }
        }while(next_permutation(p, p+n));
        printf("
    %d
    
    ", ans);
    }
    
    int main() 
    {
      int n;
      int a[15][15];
      while(scanf("%d", &n)!=EOF)
      {
          for(int i=1; i<=n; i++)
          for(int j=1; j<=n; j++)
          scanf("%d", &a[i][j]);
          solve(n, a);
      }
      return 0;
    }
    View Code

    稍加完善 ~ ~ ~

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    //template <typename Type> 
    int Merge_Sort(int * A, int x, int y)
    {
         int T[1000];
        int cnt = 0;
        if(y-x > 1) 
        {
            int m = x + (y-x)/2;
            int p = x, q = m, i = x;
            Merge_Sort(A, x, m);
            Merge_Sort(A, m, y);
            while(p < m || q < y)
            {
                if(q >= y ||(p<m && A[p] <= A[q])) T[i++] = A[p++];
                else  {    T[i++] = A[q++]; cnt += m-p;}
            }     
        }
        return cnt;
    }            
    
    template <typename TT>
    void solve(int n,  TT a[15][15])
    {
        int flag = 0; 
        TT ans=0;
        int p[15];
        for(int i=0; i<n; i++) 
        p[i] = i+1;
        cout << "
        计算算式为:	"; 
        do
        {
            int ok = Merge_Sort(p, 0, n); 
            if(ok&1) 
            {
                flag++;
               printf(" - ");
                TT temp=1;
                for(int j=1, i=0; i<n; j++, i++)
                {
                    temp*= a[j][p[i]];
                    if(j!=1)printf(" * ");
                    cout << a[j][p[i]];
                    
                }
                ans-=temp;
            }
            else 
            {
               if(flag)printf(" + ");
               flag++;
                 TT temp=1;
                for(int j=1, i=0; i<n; j++, i++)
                {
                    temp*=a[j][p[i]];
                    if(j!=1)printf(" * ");
                    cout<< a[j][p[i]]; 
                }
                ans+=temp;
            }
        }while(next_permutation(p, p+n));
        cout<<endl;
        cout <<"
    
    行列式的结果为: " <<ans << endl << endl; 
    }
    
    int main() 
    {
      int n;
      double a[15][15];                    // whatever types you want 
      cout<<"请输入所求行列式的阶数: ";
      while(scanf("%d", &n)!=EOF)
      {    
             cout << "
    请输入 "<<n<< " * " <<n<< " 的行列式!
    
    "; 
          for(int i=1; i<=n; i++)
          for(int j=1; j<=n; j++)
          cin >> a[i][j]; 
          solve(n, a);
          cout<<"请输入所求行列式的阶数: ";
      }
      return 0;
    }
    View Code

            

  • 相关阅读:
    飞入飞出效果
    【JSOI 2008】星球大战 Starwar
    POJ 1094 Sorting It All Out
    POJ 2728 Desert King
    【ZJOI 2008】树的统计 Count
    【SCOI 2009】生日快乐
    POJ 3580 SuperMemo
    POJ 1639 Picnic Planning
    POJ 2976 Dropping Tests
    SPOJ QTREE
  • 原文地址:https://www.cnblogs.com/acm1314/p/4780073.html
Copyright © 2011-2022 走看看