[SDOI2006]線性方程組——高斯消元模板
阿新 • • 發佈:2018-12-13
題目大意:
求解線性方程組。 判斷惟一解,無窮解,無解的三種情況。
高斯消元:
洛谷的模板題好像怎麼打都可以過,也沒有具體區分無窮解和無解的情況,看來這個題才是高斯消元的真正模板。
惟一解:
這個大概是最好判斷的了,在每次消元的時候都沒有出現係數全部都為0的情況即整個線性方程組有惟一解。
無窮解和無解:
兩種情況的判斷稍微有一些麻煩,但是可以這樣理解:如果一個線性方程在高消的過程中出現了某一列的係數全部為0,也就是出現了自由元,那麼可以肯定一定不會存在惟一解。 那麼剩下來的元和方程則構成了一組 {未知數<方程數} 的方程組,如果這個方程是有無窮解的,那麼自由元任意取值的情況下,接下來的未知數都可以使這個方程數大於未知數的方程組恰好成立,同時其中必定有些方程之間線性相關,那麼將最後一項係數消完之後,剩下來的係數為0的方程必定全部都是這種情況: 那麼反過來,當存在自由元之後, {未知數<方程數} ,如果接來的方程不能恰好使得剩下來的未知數成立 ,那麼將會是這種情況:
於是我們只需要在存在了自由元之後,跳過這列未知數,然後接下來的未知數繼續從這個方程開始消元,判斷一下最後係數為0的方程的情況即可。 //本文純屬自己的拙見,如有錯誤,歡迎指正。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
typedef long long ll;
using namespace std;
void File(){
freopen("luogu2455.in","r",stdin);
freopen("luogu2455.out","w",stdout);
}
template <typename T>void read(T &_){
int __=0,mul=1; char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')mul=-1;
ch=getchar();
}
while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
_=__*mul;
}
const int maxn=100+10;
const double eps=1e-6;
int n,flag=1;
double a[maxn][maxn],ans[maxn];
void print(int id){
printf("Matrix #%d\n",id);
REP(i,1,(n+1)*5)putchar('-');
putchar('\n');
REP(i,1,n){
REP(j,1,n+1)printf("%.2lf ",a[i][j]);
putchar('\n');
}
REP(i,1,(n+1)*5)putchar('-');
putchar('\n');
putchar('\n');
}
void Gauss(){
int p=1;
REP(i,1,n){
DREP(j,n,p+1)if(fabs(a[j][i])>fabs(a[j-1][i]))swap(a[j],a[j-1]);
if(fabs(a[p][i])<eps)continue;
REP(j,i+1,n+1)a[p][j]/=a[p][i]; a[p][i]=1;
REP(j,p+1,n){
REP(k,i+1,n+1)a[j][k]-=a[p][k]*a[j][i];
a[j][i]=0;
}
++p;
//print(i);
}
if(p==n+1){
DREP(i,n,1){
ans[i]=a[i][n+1];
REP(j,1,n-1)a[j][n+1]-=a[j][i]*ans[i];
}
}
else{
flag=0;
REP(i,p,n)if(fabs(a[i][n+1])>eps)flag=-1;
}
}
int main(){
// File();
read(n);
REP(i,1,n)REP(j,1,n+1)read(a[i][j]);
Gauss();
if(flag==1)REP(i,1,n)printf("x%d=%.2lf\n",i,ans[i]);
else printf("%d\n",flag);
return 0;
}