A:高斯消元,这难吗?
Q:不难,只要你会线性代数初等变换
A:没去学过?。。
Q:上B站看大神讲解,去上网易公开课,看百度,买本书自己啃……
前面都是为了鼓励你们自我学习所说的肺(骗)腑(人)之言,当然这没有这么高大上
也不需要许多前置知识,只要你会十分水(难)的如何加减消元和代入消元(想当年我初中就这两个名词没写出来被扣了分。。)
如何个方程的解呢?
其实很简单,只需要用分治的思想
首先,个未知数
的方程,把
个方程中的某个未知数用加减消元法消去,
问题就变成了个方程
个未知数(
降维打击),不就完事了吗?
然后再倒着进行代入消元法
时间,愉快的结束了!!!
A:呵呵呵,怎么这么水?
Q:ORZ,大佬!
好了,根据传(装)统(B)的说法,这是维护一个上三角矩阵
维护完了以后再倒着做一遍
WOW,这也太难(懒)了,你们还是自己啃书吧!
说真的,小学生都会了(我还不如小学生!)
#include<cstdio>
#include<iostream>
#include<cmath>
#define db double
const db eps=1e-5;
using namespace std;
const int N=106;
int n;
db a[N][N],ans[N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)
scanf("%lf",&a[i][j]);
for(int i=1;i<=n;i++)
{
if(abs(a[i][i])<=eps)
{
bool f=0;
for(int j=i+1;j<=n;j++)
if(abs(a[j][i])>eps)
{
for(int k=i;k<=n+1;k++)
swap(a[i][k],a[j][k]);
f=1;
break;
}
if(f==0)
{
puts("No Solution");
return 0;
}
}
for(int j=i+1;j<=n;j++)
{
db b=a[i][i]/a[j][i];
a[j][i]=0;
for(int k=i+1;k<=n+1;k++)
a[j][k]=a[j][k]*b-a[i][k];
}
}
for(int i=n;i>=1;i--)
{
ans[i]=a[i][n+1];
for(int j=i+1;j<=n;j++)
ans[i]-=a[i][j]*ans[j];
ans[i]/=a[i][i];
}
for(int i=1;i<=n;i++)
printf("%.2lf\n",ans[i]);
return 0;
}
这同样是一道模板题
特别特别特别特别的快(恶)乐(心),比遇见风男还快乐
我们机房目前还没有一遍过的大佬。。
但不得不说这是到非常优秀的模板题,比Luogu上的模板题好无数倍
主要是他恶心恶心恶心再要判有无解,他的数据又灰常强势。
#include<cstdio>
#include<cmath>
#include<iostream>
#define db double
const db eps=1e-5;
using namespace std;
const int N=105;
int n,now;
bool f,ff;
db a[N][N],ans[N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)
scanf("%lf",&a[i][j]);
now=1; //now 记录现在的消到了第几位
ff=0;
//判断是否有无解或者多解;
//因为无解意味着必定会消到 0+0+0+0+……+0=c(c!=0)
//多解意味着会消到0+0+0+……+0=0
for(int i=1;i<=n;i++)
{
f=0;
while(now<=n&&abs(a[i][now])<=eps)
{
for(int j=i+1;j<=n;j++)
if(abs(a[j][now])>eps)
{
for(int k=now;k<=n+1;k++)
swap(a[i][k],a[j][k]);
f=1;
break;
}
if(f==0)
{
now++;
ff=1;
}
}
if(now>n) break;
for(int j=i+1;j<=n;j++)
if(abs(a[j][now])>eps)
{
double b=a[i][now]/a[j][now];
a[j][now]=0;
for(int k=now+1;k<=n+1;k++)
a[j][k]=a[j][k]*b-a[i][k];
}
now++;
if(now>n) break;
}
if(ff==1)
{
for(int i=n;i;i--)
{
bool fff=0;
for(int j=1;j<=n;j++)
if(abs(a[i][j])>eps)
{
fff=1;
break;
}
if(fff==1) break;
//前面系数全是0
if(abs(a[i][n+1])>eps)
{
puts("-1");
return 0;
} //判断无解
//无解必须在前面判断,因为无解可能出现0+0+0+……+0=0;
}
puts("0");
return 0;
}
for(int i=n;i;i--)
{
ans[i]=a[i][n+1];
for(int j=i+1;j<=n;j++)
ans[i]-=a[i][j]*ans[j];
ans[i]/=a[i][i];
}
for(int i=1;i<=n;i++)
printf("x%d=%.2lf\n",i,ans[i]);
return 0;
}
很水的高斯消元,很容易写出n+1个方程
这些方程都带着平方,是不是感觉好恶(快)心(乐)?
每个方程与第一个相减,即可得到n个可以高斯消元的方程
如当时,设球心为
,即可得到
同理类推
#include<cstdio>
#include<iostream>
#include<cmath>
#define db double
const db eps=1e-6;
using namespace std;
const int N=20;
int n;
db b[N][N],a[N][N],ans[N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n+1;i++)
for(int j=1;j<=n;j++)
scanf("%lf",&b[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
a[i][j]=(b[i+1][j]-b[1][j])*2;
a[i][n+1]+=b[i+1][j]*b[i+1][j]-b[1][j]*b[1][j];
}
for(int i=1;i<=n;i++)
{
if(abs(a[i][i])<=eps)
for(int j=i+1;j<=n;j++)
{
if(abs(a[j][i])>eps)
{
for(int k=i;k<=n+1;k++)
swap(a[i][k],a[j][k]);
}
break;
}
for(int j=i+1;j<=n;j++)
if(abs(a[j][i])>eps)
{
db t=a[i][i]/a[j][i];
a[j][i]=0;
for(int k=i+1;k<=n+1;k++)
a[j][k]=a[j][k]*t-a[i][k];
}
}
for(int i=n;i>=1;i--)
{
ans[i]=a[i][n+1];
for(int j=i+1;j<=n;j++)
ans[i]-=ans[j]*a[i][j];
ans[i]/=a[i][i];
}
for(int i=1;i<=n;i++)
printf("%.3lf%c",abs(ans[i])<=eps?0.0:ans[i],i==n?'\n':' ');
return 0;
}