题解 P3389 【【模板】高斯消元法】
update:麻烦了管理员,发现BUG了
这篇题解介绍两种方法~~~
具体实现过程参照其他题解,这里提供两种方法的优劣
法1 高斯消元
初始形式:
结束形式:
即化为上三角形式
时间复杂度:
优点:
对于无解的判断:某一行前
对于无数解的判断:某一行
缺点:
实现行数:需要回带,约 40 行(较复杂)
法2:高斯-约旦消元
初始形式:
结束形式:
即化为对角线形式
复杂度:
优点:
实现行数:无需回带,约 25 行(较简单)
缺点:
只能判断是否有唯一解,无法判断究竟是无解还是无数解。
法1代码:
#include<bits/stdc++.h>
using namespace std;
const int N=105;
double a[N][N];
double x[N], eps=1e-6;
int solve(int n, int m){
int c=0;
int r;
for(r=0;r<n&&c<m;r++,c++){
int maxr=r;
for(int i=r+1;i<n;i++){
if(abs(a[i][c])>abs(a[maxr][c]))
maxr=i;
}
if(maxr!=r) swap(a[r], a[maxr]);
if(fabs(a[r][c])<eps){
r--;
continue;
}
for(int i=r+1;i<n;i++){
if(fabs(a[i][c])>eps){
double k=a[i][c]/a[r][c];
for(int j=c;j<m+1;j++) a[i][j]-=a[r][j]*k;
a[i][c]=0;
}
}
}
for(int i=r;i<m;i++){
if(fabs(a[i][c])>eps) return -1;//无解
}
if(r<m) return m-r;//返回自由元个数
for(int i=m-1;i>=0;i--){
for(int j=i+1;j<m;j++) a[i][m]-=a[i][j]*x[j];
x[i]=a[i][m]/a[i][i];
}
return 0;//有唯一解
}
int main() {
int n;
cin>>n;
for(int i=0;i<n;i++) {
for(int j=0;j<=n;j++) {
cin>>a[i][j];
}
}
int pan=solve(n, n);
if(pan!=0) {
cout<<"No Solution";
return 0;
}
for(int i=0;i<n;i++) {
printf("%.2lf\n", x[i]);
}
}
法2代码:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,pl;
double a[1001][1001];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++)
{
pl=i;
for(int j=i;j<=n;j++) {
if(a[j][i]>a[pl][i]) pl=i;
}
if(a[pl][i]==0) {cout<<"No Solution";return 0;} //无解或有自由元
for(int j=1;j<=n+1;j++)
swap(a[i][j],a[pl][j]);
double k=a[i][i];
for(int j=1;j<=n+1;j++)
a[i][j]=a[i][j]/k;
for(int j=1;j<=n;j++)
{
if(i!=j)
{
double ki=a[j][i];
for(int m=1;m<=n+1;m++)
a[j][m]=a[j][m]-ki*a[i][m];
}
}
}
for(int i=1;i<=n;i++)
printf("%.2lf\n",a[i][n+1]);
return 0;
}
参考博客:
https://blog.csdn.net/u011815404/article/details/88890702
https://www.cnblogs.com/xcg123/p/10679600.html