题解 P4035 【[JSOI2008]球形空间产生器】

· · 题解

A Solution For P4035 Problem

写了两天终于搞懂了!!!
坚持写小白都能看懂的题解!!!

说实话,本蒟蒻是第一次学习高斯消元,写这篇题解旨在加深自己的理解,以及帮助一下打算学习高斯消元的同学。
以下一部分来自李煜东老师的《算法竞赛——进阶指南 0x35》(详见P155)

至此,我们最后得到的是“阶梯型矩阵
该矩阵表达的是:

x_1+2x_2-x_3=-6 x_2+x_3=1 x_3=3

我们已经知道了 x_3 的值,所以能够代入求解
如果我们对方程组进一步化简,能够得到下面的表格:

最后:
这个最终的矩阵叫“简化阶梯型矩阵
引出定义:
通过初等行变换把增广矩阵变为简化阶梯型矩阵的线性方程组求解算法就是高斯消元算法

综上所述,可以大致分为三种情况:
1.高斯消元完成后,若存在系数全为0、常数不为0的行,则方程组无解。
2.若系数不全为0的行恰好有n个,则主元有n个,方程组有唯一解。
3.若系数不全为0 的行有k<n个,则主元有k个,自由元有n-k个,方程组有无穷多个解

到这里,我们的基础知识就讲完了,你,看懂了吗?

so,我们要对这个增广矩阵进行高斯消元:

下面就是代码时间啦:

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;

inline int read(){
    int x=0,w=1;
    char ch=getchar();
    for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    return x*w;
}

double a[20][20],b[20],c[20][20];//c:矩阵系数  b:常数  两者构成增广矩阵  
int n;

int main(){
    n=read();
    for(int i=1;i<=n+1;i++)
        for(int j=1;j<=n;j++)
            scanf("%lf",&a[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            c[i][j]=2*(a[i][j]-a[i+1][j]);
            b[i]+=a[i][j]*a[i][j]-a[i+1][j]*a[i+1][j];
        }
    //高斯消元(数据保证有唯一解)
    for(int i=1;i<=n;i++){//找到x[i]系数不为0的一个方程
        for(int j=i;j<=n;j++){
            if(fabs(c[j][i]>1e-8)){
                for(int k=1;k<=n;k++)
                    swap(c[i][k],c[j][k]);
                swap(b[i],b[j]);
            }
        }
    //消去其他方程x[i]的系数
        for(int j=1;j<=n;j++){
            if(i==j) continue;
            double rate=c[j][i]/c[i][i];
            for(int k=i;k<=n;k++) c[j][k]-=c[i][k]*rate;
            b[j]-=b[i]*rate;
        }
    }
    for(int i=1;i<n;i++)
        printf("%0.3lf ",b[i]/c[i][i]);
    printf("%.3lf\n",b[n]/c[n][n]);
    return 0;
}

emmmm,终于写完啦,希望讲懂了(逃~