解题思路
所以第i个未知数(在第i列)最后只能在第i行有系数,其他行第i列的系数都被消成了0。
在这里要注意一下,我们往往是将第i个未知数系数绝对值最大的方程移到第i行,这样就可以减小误差。(证明不会啊哈哈哈)
所以我们先将矩阵变成这样:
接着在处理第
i
i
i个未知数时,我们以第i个式子作为主元,用主元式去消其他式子第i列的系数并更新
i
+
1
i+1
i+1~
n
+
1
n+1
n+1列其他未知数的系数。(
1
1
1~
i
−
1
i-1
i−1的已经被消成
0
0
0了,第
n
+
1
n+1
n+1列的是每个等式右边的答案)
那怎么消呢??
我们换个方程吧,上面那个太难搞:
- 4 x + 2 y = 10 4x+2y=10 4x+2y=10
- 2 x + 3 y = 7 2x+3y=7 2x+3y=7
处理第 1 1 1列,以第一个式子为主元,第一个式子要先乘 2 4 \frac{2}{4} 42,(因为要让第一个式子乘某个系数被第二个式子减,让第二个式子的第一项系数为0)
- 2 x + y = 5 2x+y=5 2x+y=5
- 2 x + 3 y = 7 2x+3y=7 2x+3y=7
让二式变成二式减一式:
- 2 x + y = 5 2x+y=5 2x+y=5
- 0 x + 2 y = 2 0x+2y=2 0x+2y=2
成功让第一列只有第一行有系数。
第二列的处理一样,让第二行系数乘
1
2
\frac{1}{2}
21用第一行减第二行变成新的第一行。
OK,具体实现看代码吧。
代码
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
#define ldb long double
using namespace std;
int n;
ldb a[110][110];
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++)
{
int x=i;
for(int j=i+1;j<=n;j++)
if(abs(a[j][i])>abs(a[x][i]))
x=j;
if(a[x][i]==0)
{
printf("No Solution\n");
return 0;
}
for(int j=1;j<=n+1;j++)
swap(a[x][j],a[i][j]);
for(int j=1;j<=n;j++)
{
if(i!=j)
{
ldb tmp=a[j][i]/a[i][i];
for(int t=i;t<=n+1;t++)
a[j][t]-=a[i][t]*tmp;
}
}
}
for(int i=1;i<=n;i++)
{
printf("%.2Lf\n",a[i][n+1]/a[i][i]);
}
}