相关公式
需求得矩阵A的行列式det(A),求出A的伴随矩阵,每个元素除以det(A)即求得逆矩阵
求行列式
代码中计算n阶行列式的方式:用深度优先搜索算法获取n个不同行不同列元素的乘积,
用一个函数确定奇偶排列,将它们相加。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int serh(int a[]) { int cnt=0; for(int j=1;j<n;++j) { for(int i=j+1;i<=n;++i) if(a[j]>a[i]) ++cnt; } if(cnt%2) return 0; return 1; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
void dfs(int row,int k) { if(row==n+1) { int temp=-1; if(serh(order)) temp=1; sum+=temp*k; return; } for(int i=1;i<=n;++i) { if(book[i]==0) { order[row]=i; book[i]=1; dfs(row+1,k*a[row][i]); book[i]=0; } } return; }
|
总代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| #include<iostream> using namespace std; int book[101],sum,n;
int a[101][101],order[101]; int serh(int a[]); void dfs(int row,int k); int main() { cin>>n; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) cin>>a[i][j]; dfs(1,1); cout<<sum; return 0; }
void dfs(int row,int k) { if(row==n+1) { int temp=-1; if(serh(order)) temp=1; sum+=temp*k; return; } for(int i=1;i<=n;++i) { if(book[i]==0) { order[row]=i; book[i]=1; dfs(row+1,k*a[row][i]); book[i]=0; } } return; }
int serh(int a[]) { int cnt=0; for(int j=1;j<n;++j) { for(int i=j+1;i<=n;++i) if(a[j]>a[i]) ++cnt; } if(cnt%2) return 0; return 1; }
|
求逆
可将求伴随矩阵与求逆的过程合并
遍历矩阵A,求出每个元素的代数余子式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| double rac(vector<vector<double> > a);
vector<vector<double> > a(n+1,vector<double>(n+1));
vector<vector<double> > rev(n+1,vector<double>(n+1));
vector<vector<double> > rc(n,vector<double>(n)); double xy;
for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j) { int te1=1,te2=1; for(int k=1;k<=n;++k){ for(int m=1;m<=n;++m) { if(k!=i&&m!=j) { rc[te1][te2]=a[k][m]; te1++; if(te1==n) { te2++; te1=1; } } } } if((j+i)%2) xy=-1.0; else xy=1.0; rev[j][i]=xy*rac(rc)/deta; } }
|
注意
最后,如果打印rev,如下
1 2 3 4 5 6
| for(int i=1;i<=n;++i) { for(int j=1;j<=n;++j) printf("%.2f ",rev[i][j]); putchar('\n'); }
|
可能会打出-0.00,如图
这是由于浮点数精度导致,0是不在浮点数表示范围内的
把打印语句改为
1 2 3 4 5 6 7 8 9 10
| for(int i=1;i<=n;++i) { for(int j=1;j<=n;++j){ if(rev[i][j]<=0&&(rev[i][j]+0.05>0)){ printf("0.00 "); } printf("%.2f ",rev[i][j]); } putchar('\n'); }
|
即可解决问题