[JSOI2008]球形空间产生器

传送门

我们把球心坐标看做方程的一组解,之后我们设这个高维球体的半径是r。

这样我们可以同时列出n+1个方程:$$\sum_{i=1}^n(a_i - b_i)^2 = r^2$$

把方程拆开得到$$\sum_{i=1}^n(-2a_ib_i) + \sum_{i=1}nb_i2 - r^2 = \sum_{i=1}n-a_i2$$

因为\(\sum_{i=1}^nb_i^2 - r^2\)是一个与球面上点无关的量,我们直接把它设为一个新的变量,系数为1即可。之后我们就套用高斯消元解方程组。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define pr pair<int,int>
#define mp make_pair
#define fi first
#define sc second
using namespace std;
typedef long long ll;
const int M = 100005;
const int N = 10000005;
 
int read()
{
   int ans = 0,op = 1;char ch = getchar();
   while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
   while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
   return ans * op;
}

int n;
double a[15][15],ans[15];

void gauss()
{
   rep(i,1,n)
   {
      int r = i;
      rep(j,i+1,n) if(fabs(a[r][i]) < fabs(a[j][i])) r = j;
      if(r != i) swap(a[i],a[r]);
      double div = a[i][i];
      rep(j,i,n+1) a[i][j] /= div;
      rep(j,i+1,n)
      {
     div = a[j][i];
     rep(k,i,n+1) a[j][k] -= a[i][k] * div;
      }
      ans[n] = a[n][n+1];
      per(i,n-1,1)
      {
     ans[i] = a[i][n+1];
     rep(j,i+1,n) ans[i] -= a[i][j] * ans[j];
      }
   }
}

int main()
{
   n = read(),n++;
   rep(i,1,n)
   {
      rep(j,1,n-1) scanf("%lf",&a[i][j]),a[i][n+1] -= a[i][j] * a[i][j],a[i][j] *= -2.0;
      a[i][n] = 1;
   }
   gauss();
   rep(i,1,n-1) printf("%.3lf ",ans[i]);enter;
   return 0;
}

posted @ 2018-12-22 11:31  CaptainLi  阅读(158)  评论(0编辑  收藏  举报