顾名思义就是我们初中所知的消元方程,用来解方程的,但是如果自己手动去实现的话,还是有一部分难度的,因此我们也会用到线代这门科目,因为这是实现计算自动化的关键步骤
现在这里放上高斯消元的板子(可以用于区分有解,有无数组解和无解的情况)
void Gauss() //高斯消元
{
for(int i=1;i<=n;i++)
{
int maxn=i;
for(int j=1;j<=n;j++)
{
if(fabs(a[j][j])>eps&&j<i)
{
continue;//若在i前,且的确已对应一项系数,不可用
}
if(fabs(a[j][i])>fabs(a[maxn][i]))
{
maxn=j;
}
}
if(maxn!=i)
swap(a[maxn],a[i]);
if(fabs(a[i][i])<=eps)
{
continue;
}
double div=a[i][i];
for(int j=i;j<=n+1;j++)
{
a[i][j]/=div;
}
for(int j=1;j<=n;j++)
{
if(i==j)
continue;
div=a[j][i];
for(int k=i;k<=n+1;k++)
{
a[j][k]-=div*a[i][k];
}
}
}
}
例题
P3389 【模板】高斯消元法
纯板子题甚至不需要区分有无数组解和无解的情况,在上面板子优化代码即可
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
double a[105][105];
double ans[105];//统计每个数的结果
double flag=1e-7;//用来判断是否会小于0
signed 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++)
{
int r=i;//用来找到最大行
for(int j=i+1;j<=n;j++)
{
if(fabs(a[r][i])<fabs(a[j][i]))
{
r=j;
}
}
if(fabs(a[r][i])<flag)
{
cout<<"No Solution\n";
return 0;
}
if(i!=r)
{
swap(a[i],a[r]);
}
double div=a[i][i];
for(int j=i;j<=n+1;j++)
{
a[i][j]/=div;
}
for(int j=i+1;j<=n;j++)
{
div=a[j][i];
for(int k=i;k<=n+1;k++)
{
a[j][k]-=div*a[i][k];
}
}
}
ans[n]=a[n][n+1];
for(int i=n-1;i>=1;i--)
{
ans[i]=a[i][n+1];
for(int j=i+1;j<=n;j++)
{
ans[i]-=(a[i][j]*ans[j]);
}
}
for(int i=1;i<=n;i++)
{
printf("%.2lf\n",ans[i]);
}
return 0;
}
P2455 [SDOI2006] 线性方程组
就是加了一个需要区分无数组解和无解的情况,这个直接用上面的板子即可
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
double a[55][55];
double eps=1e-7;
signed 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++)
{
int r=i;
for(int j=1;j<=n;j++)
{
if(fabs(a[j][j])>eps&&j<i)
{
continue;
}
if(fabs(a[j][i])>fabs(a[r][i]))
{
r=j;
}
if(r!=i)
{
swap(a[i],a[r]);
}
if(fabs(a[i][i])<=eps)
{
continue;
}
double div=a[i][i];
for(int j=i;j<=n+1;j++)
{
a[i][j]/=div;
}
for(int j=1;j<=n;j++)
{
if(i==j)//防止自己行-自己行
continue;
div=a[j][i];
for(int k=i;k<=n+1;k++)
{
a[j][k]-=div*a[i][k];
}
}
}
}
//特判情况
int flag=1;
for(int i=1;i<=n;i++)
{
if(fabs(a[i][i])<=eps)
{
if(fabs(a[i][n+1])>eps)
{
flag=-1;
}
else if(flag!=-1)
{
flag=0;
}
}
}
if(flag!=1)
{
cout<<flag<<"\n";
}
else
{
for(int i=1;i<=n;i++)
{
cout<<"x"<<i<<"=";
printf("%.2lf\n",fabs(a[i][n+1])<eps?0:a[i][n+1]);
}
}
return 0;
}
P4035 [JSOI2008] 球形空间产生器
高斯消元的变式,推一下就出公式了,很简单,明天讲解为什么
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
double a[15][15];
double mp[15][15];
double eps=1e-7;
void Gauss() //高斯消元
{
for(int i=1;i<=n;i++)
{
int maxn=i;
for(int j=1;j<=n;j++)
{
if(fabs(a[j][j])>eps&&j<i)
{
continue;//若在i前,且的确已对应一项系数,不可用
}
if(fabs(a[j][i])>fabs(a[maxn][i]))
{
maxn=j;
}
}
if(maxn!=i)
swap(a[maxn],a[i]);
if(fabs(a[i][i])<=eps)
{
continue;
}
double div=a[i][i];
for(int j=i;j<=n+1;j++)
{
a[i][j]/=div;
}
for(int j=1;j<=n;j++)
{
if(i==j)
continue;
div=a[j][i];
for(int k=i;k<=n+1;k++)
{
a[j][k]-=div*a[i][k];
}
}
}
}
signed main()
{
cin>>n;
for(int i=1;i<=n+1;i++)
{
for(int j=1;j<=n;j++)
{
cin>>mp[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int k=1;k<=n;k++)
{
a[i][k]=mp[i+1][k]-mp[i][k];
a[i][n+1]+=(mp[i+1][k]*mp[i+1][k]-mp[i][k]*mp[i][k])/2;
}
}
Gauss();
for(int i=1;i<=n;i++)
{
printf("%.3lf ",fabs(a[i][n+1])<=eps?0:a[i][n+1]);
}
return 0;
}