1. 程式人生 > >[SDOI2006]線性方程組——高斯消元模板

[SDOI2006]線性方程組——高斯消元模板

題目大意:

求解線性方程組。 判斷惟一解,無窮解,無解的三種情況。

高斯消元:

洛谷的模板題好像怎麼打都可以過,也沒有具體區分無窮解和無解的情況,看來這個題才是高斯消元的真正模板。

惟一解:

這個大概是最好判斷的了,在每次消元的時候都沒有出現係數全部都為0的情況即整個線性方程組有惟一解。

無窮解和無解:

兩種情況的判斷稍微有一些麻煩,但是可以這樣理解:如果一個線性方程在高消的過程中出現了某一列的係數全部為0,也就是出現了自由元,那麼可以肯定一定不會存在惟一解。 那麼剩下來的元和方程則構成了一組 {未知數<方程數} 的方程組,如果這個方程是有無窮解的,那麼自由元任意取值的情況下,接下來的未知數都可以使這個方程數大於未知數的方程組恰好成立,同時其中必定有些方程之間線性相關,那麼將最後一項係數消完之後,剩下來的係數為0的方程必定全部都是這種情況: 0

×xi=00×xn1=00×xn=00\times x_{i}=0\\ \vdots \\ 0\times x_{n-1}=0\\ 0\times x_n=0 那麼反過來,當存在自由元之後, {未知數<方程數} ,如果接來的方程不能恰好使得剩下來的未知數成立 ,那麼將會是這種情況: in,0×xi=a(a̸=0)\exists i\in n, \ 0\times x_i=a (a\not= 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; }