在普通的高斯消元中,我们可以直接将矩阵削成对角线矩阵。
void gauss(double sz[1002][1002],int n,double ans[1002])
{
for(int i=0;i<n;i++)
{
int wz=i;
for(int j=i+1;j<n;j++)
{
if(fabs(sz[j][i])>fabs(sz[wz][i]))
wz=j;
}
if(fabs(sz[wz][i])<eps)continue;//1
if(i!=wz)
{
for(int j=i;j<=n;j++)
{
double t=sz[i][j];
sz[i][j]=sz[wz][j];sz[wz][j]=t;
}
}
double z=sz[i][i];
for(int j=i;j<=n;j++)sz[i][j]/=z;
for(int j=0;j<n;j++)
{
if(j==i||fabs(sz[j][i])<eps)continue;
double t=sz[j][i];
for(int k=i;k<=n;k++)
sz[j][k]-=sz[i][k]*t;
}
}
for(int i=0;i<n;i++)
ans[i]=sz[i][n]/sz[i][i];
}
但是,如果发生“1”处的问题,说明无解或有无穷解。
无解情况就是说,在某一行上出现了"(0 imes x=a(a!=0))"的情况,这可以直接判掉。
在无穷解时,由于1后面的语句没有执行,因此只能将矩阵削成上三角矩阵。
此时,若一个未知数有确定的解,那么在那一行,也会有且只有一个非0数,这也可以直接判掉。
之后,剩余的未知数若在对角线上为0,则它是自由元。否则,可以用已经算出的未知数消去那一行,将它变为自由元的表达式。
在解决关灯问题时,可以直接(2^n)枚举所有自由变元,然后把它们代入求出剩余的未知数。