如果你覺得這篇太囉嗦
問題
[SDOI2006] 線性方程組
題目描述
已知 \(n\) 元線性一次方程組。
\[\begin{cases} a_{1, 1} x_1 + a_{1, 2} x_2 + \cdots + a_{1, n} x_n = b_1 \\ a_{2, 1} x_1 + a_{2, 2} x_2 + \cdots + a_{2, n} x_n = b_2 \\ \cdots \\ a_{n,1} x_1 + a_{n, 2} x_2 + \cdots + a_{n, n} x_n = b_n \end{cases}
\]
請根據輸入的資料,程式設計輸出方程組的解的情況。
題解
打眼一看,這不是大版汁嘛😎。立刻把這個題的程式碼直接提交:
#include<bits/stdc++.h>
using namespace std;
double mapp[110][110],ans[110];
int n;
int main(){
cin>>n;
int r;
for(int i=1;i<=n;i++){
for(int j=1;j<=n+1;j++){
cin>>mapp[i][j];
}
}
for(int i=1;i<=n;i++){
r=i;
for(int j=i;j<=n;j++){
if(fabs(mapp[r][i])<fabs(mapp[j][i])){
r=j;
}
}
if(fabs(mapp[r][i])<1e-7){
cout<<"No Solution"<<endl;
return 0;
}
swap(mapp[i],mapp[r]);
double t=mapp[i][i];
for(int j=i;j<=n+1;j++){
mapp[i][j]/=t;
}
for(int j=i+1;j<=n;j++){
t=mapp[j][i];
for(int k=i;k<=n+1;k++){
mapp[j][k]-=mapp[i][k]*t;
}
}
}
ans[n]=mapp[n][n+1];
for(int i=n-1;i>=1;i--){
ans[i]=mapp[i][n+1];
for(int j=i+1;j<=n;j++){
ans[i]-=mapp[i][j]*ans[j];
}
}
for(int i=1;i<=n;i++){
printf("x%d=%.2lf\n",i,ans[i]);
}
}
o,我沒有仔細讀題,還要再判斷是無解還是無窮解。
😕看來並沒有那麼簡單,但注意到,可以透過一個計數器來記錄是什麼時候break掉的,如果計數器不等於n,就要進行判斷:
if(t!=n){
if(mapp[t][n+1]){
cout<<-1;
return 0;
}
else{
cout<<0;
return 0;
}
}
那麼加上最佳化,我們的程式碼變成了幾分呢?
🤡這不純純消愁嘛
經過一番排查,發現了一個顯而易見的問題:要一層層的排查t以後的層數(除了我這個蒟蒻都能看出來吧)
if(t<n){
while(t<n){
if(mapp[t++][n]<1e-7){
cout<<-1;
return 0;
}
}
cout<<0;
return 0;
}
這個最佳化立竿見影!
🎉️耶!
但有些聰明的人肯定已經發現了問題:測試點12本來是A的,但加上最佳化就戳了:(
但是愚蠢的LEWIAK並沒有發現,拿著錯誤程式碼調了114分鐘
這時,我靈機一動💡,想直接返璞歸真暴力判斷是否為完美梯形:
if(tt<n){
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
if(!mapp[i][j]){
if(mapp[i][n+1]){
cout<<-1;
return 0;
}
}
}
}
cout<<0;
return 0;
}
那麼返璞歸真後,我們的程式碼變成了幾分呢?
🤡
還有翻轉!
但有些聰明的人肯定已經發現了問題:測試點12本來是A的,但加上最佳化就戳了:(
的原因其實是:
變數名衝突
最離譜的是我的婢養的DEV C++竟然沒有檢查出錯(不是哥們,他一個int一個double都不報錯的嗎?)
😁很有希望!
但是愚蠢的LEWIAK調了半天后發現了嚴重的問題
那就是我們的程式碼實際上並沒有處理完成所有的消元👀️
倒是也好處理😎,把break換為continue就好了。
🤓🤓🤓
想了想發現:應該把i換成tt,因為有一些是不算的:
(懶得貼了,自己想象WA的評測資訊吧)
🤓🤓🤓
經過苦思冥想,我發現要用別的多項式消掉continue的,而為了節省空間,我決定無腦的將從i到n的迴圈改為從1到n的迴圈
其實LEWISAK只是懶的用陣列單獨儲存罷了
最後貼上ACcode:
#include<bits/stdc++.h>
using namespace std;
double mapp[110][110],ans[110];
int tt=0;
int n;
int main(){
cin>>n;
int r;
for(int i=0;i<n;i++){
for(int j=0;j<n+1;j++){
cin>>mapp[i][j];
}
}
for(int i=0;i<n;i++){
r=tt;
for(int j=tt+1;j<n;j++){
if(fabs(mapp[r][i])<fabs(mapp[j][i])){
r=j;
}
}
if(fabs(mapp[r][i])<1e-9){
continue;
}
for(int j=0;j<n+1;++j)swap(mapp[tt][j],mapp[r][j]);
double t;
for(int j=0;j<n;j++){
if(j==tt){
continue;
}
t=mapp[j][i]/mapp[tt][i];
for(int k=i;k<n+1;k++){
mapp[j][k]-=mapp[tt][k]*t;
}
}tt++;
}
if(tt<n){
while(tt<n){
if(fabs(mapp[tt++][n])>=1e-9){
cout<<-1;
return 0;
}
}
cout<<0;
return 0;
}
for(int i=0;i<n;i++){
printf("x%d=%.2lf\n",i,mapp[i][n]/mapp[i][i]);
}
}
改馬蜂是因為玄學