• 行列式计算(编程实现)


                                                           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

            

  • 相关阅读:
    阿里云esc 安装 mysql8.0
    阿里云esc 登录时的相关提示
    C# web项目 log4net 使用
    MVC 全局异常捕获
    datetimepicker 基础使用/select2 基础使用
    C# 从登陆开始 MVC4+BOOTSTRAP
    Android如何导入语言资源
    Android自带邮件含中文的附件用HTML打开乱码问题的解决
    android 解决输入法遮挡输入框的问题
    repo代码简单解读
  • 原文地址:https://www.cnblogs.com/acm1314/p/4780073.html
Copyright © 2020-2023  润新知