题目链接
http://www.lydsy.com/JudgeOnline/problem.php?id=1013
思路
非常好的高斯消元练习题。。。
首先我们设在
n
维空间中,点a的坐标为
则
(b1−x1)2+(b2−x2)2+...+(bn−xn)2=r2...②
看上去这两个式子都是二次的,不能套用一次的高斯消元,但是当我们
①−②
后,神奇的一幕发生了:
(a1−b1)x1+(a2−b2)x2+...+(an−bn)xn=(a21−b21)+(a22−b22)+...+(a2n−b2n)2
由于此题有
n
个未知数,我们需要
以第一个点的坐标和第
2
~
然后高斯消元搞定
蒟蒻我居然打错了高斯消元的交换行操作,WA了3发,我太弱了。。。
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#define MAXN 1100
using namespace std;
double pos[MAXN],a[MAXN][MAXN],ans[MAXN]; //pos[]保存第一个点的坐标,ans[]保存解
void Gauss(int n) //求n元一次方程
{
for(int i=1;i<=n;i++) //上三角变换
{
int maxr=0;
for(int j=i;j<=n;j++)
if(fabs(a[j][i])>fabs(a[maxr][i]))
maxr=j;
for(int j=1;j<=n+1;j++) //!!!!!交换行,使得第i行的第i个元素是所有行里最大的
swap(a[i][j],a[maxr][j]);
for(int j=i+1;j<=n;j++) //将第j行的第i个元素消去
{
double tmp=-a[j][i]/a[i][i];
for(int k=i;k<=n+1;k++) //!!!!!!!
a[j][k]+=a[i][k]*tmp;
}
}
for(int i=n;i>=1;i--) //回代
{
for(int j=n;j>i;j--) //第i行的i+1~n列都要消去
a[i][n+1]-=a[i][j]*ans[j];
ans[i]=a[i][n+1]/a[i][i]; //!!!!!!
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf",&pos[i]);
for(int i=1;i<=n;i++)
{
double tmp[MAXN];
for(int j=1;j<=n;j++)
scanf("%lf",&tmp[j]);
for(int j=1;j<=n;j++)
{
a[i][j]=pos[j]-tmp[j];
a[i][n+1]+=(pos[j]*pos[j]-tmp[j]*tmp[j])/2;
}
}
Gauss(n);
for(int i=1;i<=n;i++)
printf("%.3lf%c",ans[i],i==n?'\n':' ');
return 0;
}