新高斯消元-模板

i207M

2019-07-12 11:05:03

Personal

ri,NOI前又和高斯消元奋斗了1h+...为啥只有我写的是假高斯消元... ~~ri,我TM交换行列没交换全,ri~~ 先来一个完全正确的版本: ```cpp int gauss(int n) { for(ri i=1,p,c=1;i<=n;++i) { for(p=c;p<=n&&!sgn(g[p][i]);++p); if(p==n+1) continue; if(p!=c) for(ri j=i;j<=n+1;++j) swap(g[p][j],g[c][j]); for(ri j=c+1;j<=n;++j) if(sgn(g[j][i])) { double t=g[j][i]/g[c][i]; for(ri k=i;k<=n+1;++k) g[j][k]-=t*g[c][k]; } ++c; } bool inf=0; for(ri i=n;i>=1;--i) { bool hv=0; for(ri j=i;j<=n;++j) if(sgn(g[i][j])) { hv=1; break; } if(!hv) { if(sgn(g[i][n+1])) return -1; else {inf=1; continue;} } ans[i]=g[i][n+1]; for(ri j=i+1;j<=n;++j) ans[i]-=g[i][j]*ans[j]; ans[i]/=g[i][i]; } return inf?0:1; } ``` 简单的说,就是我们**必须消成全零行**!我们要维护一个列指针i,和行指针c。关于判断无解,我们对每一个等式,看是否左边系数全为0,常数不为0的情况——无解;等于0——无穷解,但是这是不要急着返回,因为可能还有无解的情况。 ------------ 如果只要判断是否有唯一解,可以用偷懒的方法: ```cpp for(ri i=1;i<=n;++i) { if(!sgn(g[i][i])) { int k=-1; for(ri j=i+1;j<=n;++j) if(sgn(g[j][i])) { k=j; break; } if(k==-1) continue; for(ri j=i;j<=n+1;++j) swap(g[i][j],g[k][j]); } for(ri j=n+1;j>=i;--j) g[i][j]/=g[i][i]; for(ri j=i+1;j<=n;++j) if(sgn(g[j][i])) { for(ri k=n+1;k>=i;--k) g[j][k]-=g[j][i]*g[i][k]; } } ```