[JSOI2008]球形空间产生器sphere(高斯消元+数学)

题意:传送门

题解:首先可以列出每个点到圆心的方程,一下均以二维举例:

(x1-x0)^2+(y1-y0)^2=r^2

(x2-x0)^2+(y2-y0)^2=r^2

(x3-x0)^2+(y3-y0)^2=r^2

展开得到:

x1^2-2*x0*x1+x0^2+y1^2-2*y0*y1+y0^2=r^2

x2^2-2*x0*x2+x0^2+y2^2-2*y0*y2+y0^2=r^2

x3^2-2*x0*x3+x0^2+y3^2-2*y0*y3+y0^2=r^2

接着还是看不出啥,但是用1式减2式,用2式减3式得到:

2*(x2-x1)*x0+2*(y2-y1)*y0=x2^2-x1^2+y2^2-y1^2

2*(x3-x2)*x0+2*(y3-y2)*y0=x3^2-x2^2+y3^2-y2^2

之后使用高斯消元就得到了解,推广到n维也是这样做。

附上代码:


#include<bits/stdc++.h>

using namespace std;

const int maxn=15;

int n;
double s[maxn][maxn];
double a[maxn][maxn];
double ans[maxn];

void swap_r(int q,int p)
{
    for(int i=1;i<=n+1;i++){
        double t=a[p][i];
        a[p][i]=a[q][i];
        a[q][i]=t;
    }
}

void swap_c(int q,int p)
{
    for(int i=1;i<=n+1;i++){
        double t=a[i][p];
        a[i][p]=a[i][q];
        a[i][q]=t;
    }
}

void gs()
{
    for(int i=1;i<n;i++){
        double m=fabs(a[i][i]);
        int p=i,q=i;
        for(int j=i+1;j<=n;j++){
            for(int k=i;k<=n;k++){
                if(fabs(a[j][k])>m){
                    m=fabs(a[j][k]);
                    p=j;
                    q=k;
                }
            }
        }
        if(p!=i){
            swap_r(p,i);
        }
        if(q!=i){
            swap_c(q,i);
        }
        for(int j=i+1;j<=n;j++){
            if(a[i][j]==0.0){
                continue;
            }
            double t=a[j][i]/a[i][i];
            a[j][i]=0.0;
            for(int k=i+1;k<=n+1;k++){
                a[j][k]-=t*a[i][k];
            }
        }
    }
}

void red()
{
    for(int i=n;i>1;i--){
        for(int j=i-1;j>=1;j--){
            if(a[j][i]==0){
                continue;
            }
            double t=a[j][i]/a[i][i];
            a[j][i]=0.0;
            for(int k=i+1;k<=n+1;k++){
                a[j][k]-=t*a[i][k];
            }
        }
    }
}

void solve()
{
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            a[i][j]=2*(s[i+1][j]-s[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            a[i][n+1]+=s[i+1][j]*s[i+1][j]-s[i][j]*s[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        a[n+1][i]=i;
    }
    gs();
    red();
    for(int i=1;i<=n;i++){
        ans[(int)a[n+1][i]]=a[i][n+1]/a[i][i];
    }
    printf("%.3f",ans[1]);
    for(int i=2;i<=n;i++){
        printf(" %.3f",ans[i]);
    }
    printf("\n");
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n+1;i++){
        for(int j=1;j<=n;j++){
            scanf("%lf",&s[i][j]);
        }
    }
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/86480377