【C++】超級詳細,多元一次方程的求解方法
在這個問題中,假設我們是要解一個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();
}
相關文章
- 超級詳細Tcpdump 的用法TCP
- iOS超級超級詳細介紹GCDiOSGC
- (轉)超級詳細Tcpdump 的用法TCP
- 超級詳細Tcpdump 的用法(轉)TCP
- 超級詳細的tcpdump用法介紹TCP
- SVG基礎教程(超級詳細)SVG
- Spring AOP全面詳解(超級詳細)Spring
- Java註解最全詳解(超級詳細)Java
- C++指標的概念解讀 超詳細C++指標
- HTML 超級連結詳細講解HTML
- 超級詳細的react筆記(三)jsxReact筆記JS
- A*演算法(超級詳細講解,附有舉例的詳細手寫步驟)演算法
- Android Studio安裝教程(超級詳細)Android
- 求解c++C++
- java集合梳理【10】— Vector超級詳細原始碼分析Java原始碼
- AlphaFold2無痛安裝教程(超級詳細)
- JWT 超詳細分析JWT
- :SpringBoot專案接入ELK超級版(超詳細圖文教程)Spring Boot
- 超級詳細的mac系統檔案許可權修改指南Mac
- Duboo整合SpringBoot超級詳細例子(附原始碼)Spring Boot原始碼
- Node.js非同步程式設計~超級詳細哦Node.js非同步程式設計
- GitHub和Git超超超詳細使用教程!Github
- 超詳細的Eureka原始碼解析原始碼
- 超詳細的 Vagrant 上手指南
- Vue 指令大全(超詳細)Vue
- MyBatis Generator 超詳細配置MyBatis
- Vue 超詳細手記Vue
- java運算子(超詳細!!!)Java
- Maven筆記---超詳細Maven筆記
- web259(超詳細)Web
- springboot超級詳細的日誌配置(基於logback)Spring Boot
- Vue知識點總結(3)——v-bind(超級詳細)Vue
- 超詳細的node垃圾回收機制
- (摘)sql-索引的作用(超詳細)SQL索引
- 超詳細的Ribbon原始碼解析原始碼
- 使用Jenkins優雅部署Java專案【超級詳細的實戰教程】JenkinsJava
- Go Struct超詳細講解GoStruct
- Redis安裝教程(超詳細)Redis