行列式计算的两种方法

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 100
using namespace std;
int a[N][N];
double aa[N][N];
int n;

/**********************************************************/
//求行列式的值:是所有取自不同行不同列的n个元素的乘积
int d[N];
int tmpd[N];
int dd[N];
int vis_column[N];//是否在同一列
int inverse;//逆序数的个数
int ans = 0;
void merger(int ld, int rd){
    if(ld >= rd) return;
    int mid=(ld+rd)>>1;
    merger(ld,mid);
    merger(mid+1, rd);
    int i=ld, j=mid+1, k=0;
    while(i<=mid && j<=rd){
        int col1 = (tmpd[i]-1)%n+1;
        int col2 = (tmpd[j]-1)%n+1;
        if(col1 < col2){
            dd[++k] = tmpd[i++];
        } else {
            dd[++k] = tmpd[j++];
            inverse += mid-i+1;
        }
    }
    while(i<=mid) dd[++k] = tmpd[i++];
    while(j<=rd) dd[++k] = tmpd[j++];
    memcpy(tmpd+ld, dd+1, sizeof(int)*(k));
}

void determinantValue(int row){
    if(row>n){
        inverse=0;
        int tmp = 1;
        for(int k=1; k<=n; ++k){
            int i = (d[k]-1)/n+1;
            int j = (d[k]-1)%n+1;
            tmp *= a[i][j];
        }
        memcpy(tmpd, d, sizeof(int)*(n+1));
        merger(1, n);
        if(inverse&1) ans-=tmp;
        else ans+=tmp;
        return;
    }
    for(int col=1; col<=n; ++col)
        if(!vis_column[col]){
            vis_column[col]=1;
            d[row] = (row-1)*n + col;
            determinantValue(row+1);
            vis_column[col]=0;
        }
}
/**********************************************************/

/**********************************************************/
//以列主元方法,将行列式转变成上三角矩阵

double determinantValueA(){
    int sign = 1;
    double ret = 0.0;
    for(int i=1; i<=n; ++i){
        double maxVal = aa[i][i];
        int j = i;
        for(int k=i+1; k<=n; ++k)//寻找这一列中的元素值的最大值
            if(maxVal < aa[k][i]){
                maxVal = aa[k][i];
                j = k;
            }
        if(j!=i){
            sign = -sign;
            for(int k=1; k<=n; ++k){//交换两行
                double tmp = aa[i][k];
                aa[i][k] = aa[j][k];
                aa[j][k] = tmp;
            }
        }
        if(maxVal < 1e-10)//最大值为0,也就是意味这对角线上的元素有0出现
            return ret;

        for(int k=i+1; k<=n; ++k){
            double b = aa[k][i]/aa[i][i];
            for(int c=1; c<=n; ++c)
                aa[k][c] -= b*aa[i][c];
        }
    }
    ret = 1.0;
    for(int i=1; i<=n; ++i)
        ret*=aa[i][i];
    return ret;
}

/**********************************************************/
int main() {
//    cin>>n;
//    for(int i=1; i<=n; ++i)
//        for(int j=1; j<=n; ++j)
//            cin>>a[i][j];
//    determinantValue(1);
//    cout<<ans<<endl;

    cin>>n;
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=n; ++j)
            cin>>aa[i][j];
    cout<<determinantValueA()<<endl;
    return 0;
}
/*
4
3 4 5 11
2 5 4 9
5 3 2 12
14 -11 21 29

4
2 0 0 0
0 2 0 0
0 0 2 0
0 0 0 2 

2
1 2 3 4
*/
时间: 2024-11-03 03:46:00

行列式计算的两种方法的相关文章

计算文件大小两种方法 递归和循环

递归: def list_in(s): result = 0 lst = os.listdir(s) for i in lst: i = s + "/" + i if os.path.isfile(i): result = result + os.path.getsize(i) elif os.path.isdir(i): ret = list_in(i) result = result + ret return resultprint(list_in(r"G:/salar&

利用颜色和形态学两种方法进行车牌区域提取的OpenCV代码

要想提取车牌号,首先你要定位车牌区域嘛,本文分别两种方法用,即颜色和形态学的方法,对车牌区域进行判定.说得是两种方法,其实两种方法并无多大的区别,只是有一步的判断标准不一样而已,你看了下面整理出的的思路就知道两者的区别真的很小了. 方法一:利用颜色提取车牌区域的思路: ①求得原图像的sobel边缘sobelMat ②在HSV空间内利用车牌颜色阈值对图像进行二值化处理,得到图像bw_blue→ ③由下面的判别标准得到图像bw_blue_edge for (int k = 1; k != heigh

Android第五期 - 更新自己的apk本地与网络两种方法

首先是本地: ParseXmlService部分: package com.szy.update; import java.io.InputStream; import java.util.HashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element

实现icon和文字垂直居中的两种方法-(vertical-align and line-height)

方法一:vertical-align 在w3school定义:该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐 百思不得骑姐 然后Google,反正在w3schools上面并没有找到定义 仅仅能写代码測试 而后个人理解,才作出如此解释> 该属性作用的对象:行内元素(inline,inline-block也有行内属性) 其它table-cell 经常使用属性值:top middle bottom 个人理解 个人觉得,普通情况下,这些字母自发"坐落"的这条线就是基线.然后两

WPF多线程UI更新——两种方法

WPF多线程UI更新--两种方法 前言 在WPF中,在使用多线程在后台进行计算限制的异步操作的时候,如果在后台线程中对UI进行了修改,则会出现一个错误:(调用线程无法访问此对象,因为另一个线程拥有该对象.)这是很常见的一个错误,一不小心就会有这个现象.在WPF中,如果不是用多线程的话,例如单线程应用程序,就是说代码一路过去都在GUI线程运行,可以随意更新任何东西,包括UI对象.但是使用多线程来更新UI就可能会出现以上所说问题,怎么解决?本文章提供两个方法:Dispatcher(大部分人使用),T

旧文备份:利用一个定时器实现多个虚拟定时器的两种方法

固定周期法 使用一个硬件定时器进行固定周期(比如1ms)定时,用一个结构体数组作为软定时器描述表,数组的结构体数就是最大虚拟定时器的数量,每个结构体的成员都包括虚拟定时器状态(空闲.激活.运行.超时触发.周期触发).定时值(换算成定时周期数,例如1ms的硬件定时周期,现进行125ms的定时,定时值就是125).标识ID和回调函数等:用一个变量作为定时周期计数器,每次进入定时中断,重置定时器,扫描结构体数组中的每个成员结构体,对定时值做减一操作,然后判断该定时值是否为0,是则判定该值对应的虚拟定时

【九天教您南方cass 9.1】 10 DTM土方计算的四种方法

同学们大家好,欢迎收看由老王测量上班记出品的cass9.1视频课程 我是本节课主讲老师九天. 我们讲课的教程附件也是共享的,请注意索取测量空间中. 九天老师的联系方式  点击直接请教九天老师吧! DTM土方计算的四种方法 课程教案 一.根据坐标文件. (1).-->根据坐标文件 (2).-->指定坐标文件 (3).-->DTM土方计算参数设置 (4).-->得出结果dtmtf.log (5).-->并指定三角网法土石方计算成果表的位置 二.根据图上高程点. (1).-->

智能手机的耗电特征及APP耗电量测试的两种方法

文章陈述了手机发展趋势及耗电特性,集中讨论了时下最为关心的智能手机耗电问题,并介绍了测量手机软件耗电量的两种方法.此外还解释了为何运营商此前会提出收取微信的费用,心跳机制是什么. 美国著名手机公司Palm的CEO JonRubinstein曾经说过:“手机未来的发展取决于两个因数,一是手机的数据传输速度:二就是手机待机时长.” 为什么手机待机时长如此重要呢? 现 在,手机上网速度已经有很大的提升,而且还在马不停蹄的发展4G,5G.4G网络可以将手机的上网速度提高到100Mbps以上,简单的说,下

RAID5数据丢失恢复的两种方法

如果了解RAID技术,一定对RAID级别这个词不陌生,RAID级别是指磁盘阵中磁盘组合方式,RAID级别不同,磁盘组合的方式也就不同,为用户提供的磁盘阵列在性能上和安全性的表现上也有不同.本文就是针对RAID级别中的RAID5,谈谈RAID5数据恢复的两种办法. RAID5虽然对数据传输的并行性解决不好,而且控制器的设计也相当困难,但是RAID5的读出效率很高,写入效率一般,块式的集体访问效率不错,因为奇偶校验码在不同的磁盘上,所以提高了可靠性.RAID5发生故障的原因可能有很多种,或者是RAI