在这个问题中,假设我们是要解一个N元一次的方程;
解题使用方法:
使用多元一次方程的 消去法
假设我有三个方程
2a-b+c=3 , 3a+b-c=2 , a-3b+2c=1
对第一个式子我让第一个元素为准(我们这里就叫他标准行吧,先记住这个名字!!!!!!),即a,每个方程同时除以a的系数,就变成了
a-(1/2)b+(1/2)c=3/2 , a+(1/3)b-(1/3)c=2/3 , a-3b+2c=1
然后,用第一个式子的a去替换掉其他式子的a(自身不换),也可以理解为其他式子减去用来替换a的式子,方程变为
a+2b+2c=1 , (5/6)b-(5/6)c=-(5/6) , -(5/2)b+(3/2)c=1/3
这里第二个式子和第三个式子都只有b和c,按照这种方式,我再以第二个方程为准(第二个方程作为标准行),替换掉第三个方程的b(这里为什么不替换第一个方程后面解释),这样第三个方程只剩下c,最后以第三个方程为标准行,因为它这个方程只有一个元素,可以解出c
然后将c往第二个方程中带入第二个方程(只有b,c两个元素),解出b,再带入第一个,解出a
所以,在第一次替换后,只有第一个式子有a,如果我还去替换它,那肯定算不出a的呀
储存办法:
一个多元一次的方程要用什么来储存呢?我们可以将方程储存在double m[N][N+1]数组(N个需要求解的元素,还有第N+1个位置储存方程结果)中;计算的数据结果我们可以在double s[N]数组中。
同时,还需要一个用来记录方程中用来替换其他的元素的数组int loc[N],并且初始化它为-1,元素位置不可能为-1(比如说我第二个方程第二个元素,即b元素就是用来替换其他方程的第二个元素的,则loc[1]=1,这里从0开始)
办法:解决这个问题,我们需要一些函数
1,
一个能将第h行的方程同时除以第n个元素的系数的函数
void make1(int h, int n)//使h行同时除以第n个元素
{
double t = m[h][n];//过程中第n个元素的系数会改变,所以先储存其系数
if (m[h][n] == 0)
return;
for (int i = 0; i < N + 1; i++)
m[h][i] /= t;
}
为了方便记,就记make1,make系数变为1
在轮到第n个元素做消去的时候,对所以能够除去第n个元素的系数的方程进行make1函数
void Allmake1(int n)
{
for (int i = 0; i < N; i++)
{
if (loc[i] == -1 && m[i][n] != 0)
make1(i, n);
//loc[i]==-1,说明这一行没有做过标准行
//m[i][n] != 0,说明这个方程的第n个元素系数不是0
//如果是0,除以系数是会出现分母为0的情况,答案可能会得到-inf
}
}
Allmake1,让所有系数变为一(不是真的所有)
2,在进行了除以系数的函数后,我们就要开始替换啦
min函数的作用是标准行s,对目标行h,进行替换掉第n个元素的操作
因为之前进行过所有方程的第n个元素的系数直接变成一的操作了,所以直接减法就可以让h的第n个元素消去
不应该减去的方程是:作标准行的和这个方程没有第n个元素的(n号元素在方程中系数为0)
void min(int s,int h,int n)
{
if(loc[h]==-1&&m[h][n]!=0)
for (int i = 0; i < N+1; i++)
m[h][i] -= m[s][i];
}
void Allmin(int s,int n)//对所有应该替换的程都替换掉第n个元素
{
for (int i = 0; i < N; i++)
min(s, i, n);
}
记住min消去你的第n个元素
Allmin(消去所有方程第n个元素,不是真的所有哦)
3,标记第h个方程是作为第n个元素标准行的函数
随便找一个第n个元素的系数不为0的方程(在第h行),记录loc并且用这个方程去替换除了自己以外所有这个元素的系数不为0并且没有作为标准行过的方程(这个方程在loc数组中对应值为-1)
void setloc(int h, int n)
{
loc[h] = n;
}
setloc,标记标准行
4,找到第n个元素的标准行,并对其他行进行替换的函数
void Onereplace(int n)
{
int l;
for (int i = 0; i < N; i++)
{
if (loc[i] == -1 && m[i][n] != 0)
{
l = i;
setloc(i, n);//标记标准行
make1(i, n);//使自身方程进行除法,都除以第n个元素的系数
break;
}
}
Allmake1(n);//对所有方程进行make1
Allmin(l,n);//消去第n个元素
}
void Allreplace()//从第1个元素到第n个,所有元素能换掉就换掉
{
for (int i = 0; i < N; i++)
Onereplace(i);
}
One replace,换掉所有的第n个元素
All replace,换到所有元素(不是真的所有)这就是主要的函数啦,但是你不觉得一个一个函数打出来很麻烦吗? 我干脆把他们都放在一个函数里算啦。
void pc()
{
fill(loc, loc + N, -1);
Allreplace();
Allcacular();
}
还要有一个输出元素结果的函数
void Cout()
{
for (int i = 0; i < N; i++)
cout << s[i] << " ";
cout << endl;
}
什么!你有强迫症,不想一个一个函数单独看? 行行,整合了发。
唉,随便水水字数了,好累
#include<iostream>
using namespace std;
#define N 4//我自己假设的例子,这里N等于4,结果a=1,b=2,c=3,d=4
double m[N][N + 1] = {
0,3,2,1, 16,
1,1,1,1, 10,
3,2,2,1, 17,
2,0,1,2, 13
//不放心你就自己整几个例子啊,学生也很忙的啊,现在都1:53了,肝死我了
};
double s[N];
int loc[N];
void Allmin(int s, int n);//声明函数,不然会报错
void make1(int h, int n)
{
double t = m[h][n];
if (m[h][n] == 0)
return;
for (int i = 0; i < N + 1; i++)
m[h][i] /= t;
}
void setloc(int h, int n)
{
loc[h] = n;
}
void Allmake1(int n)
{
for (int i = 0; i < N; i++)
{
if (loc[i] == -1 && m[i][n] != 0)
make1(i, n);
}
}
void Onereplace(int n)
{
int l;
for (int i = 0; i < N; i++)
{
if (loc[i] == -1 && m[i][n] != 0)
{
l = i;
setloc(i, n);
make1(i, n);
break;
}
}
Allmake1(n);
Allmin(l,n);
}
void min(int s,int h,int n)
{
if(loc[h]==-1&&m[h][n]!=0)
for (int i = 0; i < N+1; i++)
m[h][i] -= m[s][i];
}
void Allmin(int s,int n)
{
for (int i = 0; i < N; i++)
min(s, i, n);
}
void Allreplace()
{
for (int i = 0; i < N; i++)
Onereplace(i);
}
void cacular(int n)
{
for(int i=0;i<N;i++)
if (loc[i] == n)
{
for (int k = 0; k < N; k++)
if (m[i][k]!=0&&k != n)
m[i][N] -= m[i][k] * s[k];
s[n] = m[i][N] / m[i][n];
break;
}
}
void Allcacular()
{
for (int i = N - 1; i >= 0; i--)
cacular(i);
}
void pc()
{
fill(loc, loc + N, -1);
Allreplace();
Allcacular();
}
void Cout()
{
for (int i = 0; i < N; i++)
cout << s[i] << " ";
cout << endl;
}
int main()
{
pc();
Cout();
}