[题解]ZOJ 3645:BiliBili/BZOJ 1013 球形空间产生器

BiliBili

Time Limit: 2 Seconds Memory Limit: 65536 KB

Shirai Kuroko is a Senior One student. Almost everyone in Academy City have super powers, and Kuroko is good at using it. Her ability is “Teleporting”, which can make people to transfer in the eleven dimension, and it shows like moving instantly in general people’s eyes.

In fact, the theory of the ability is simple. Each time, Kuroko will calculate the distance between some known objects and the destination in the eleven dimension so that Kuroko can get the coordinate of the destination where she want to go and use her ability.

Now we have known that the coordinate of twelve objects in the eleven dimension Vi = (Xi1,Xi2, … ,Xi11), and 1 <= i <= 12. We also known that the distance Di between the destination and the object. Please write a program to calculate the coordinate of the destination. We can assume that the answer is unique and any four of the twelve objects are not on the same planar.

Input

The first line contains an integer T, means there are T test cases. For each test case, there are twelve lines, each line contains twelve real numbers, which means Xi1,Xi2, … ,Xi11 and Di. T is less than 100.

Output

For each test case, you need to output eleven real numbers, which shows the coordinate of the destination. Round to 2 decimal places.

Sample Input

1
1.0 0 0 0 0 0 0 0 0 0 0 7.0
0 1.0 0 0 0 0 0 0 0 0 0 7.0
0 0 1.0 0 0 0 0 0 0 0 0 7.0
0 0 0 1.0 0 0 0 0 0 0 0 7.0
0 0 0 0 1.0 0 0 0 0 0 0 7.0
0 0 0 0 0 1.0 0 0 0 0 0 7.0
0 0 0 0 0 0 1.0 0 0 0 0 7.0
0 0 0 0 0 0 0 1.0 0 0 0 7.0
0 0 0 0 0 0 0 0 1.0 0 0 7.0
0 0 0 0 0 0 0 0 0 1.0 0 7.0
0 0 0 0 0 0 0 0 0 0 1.0 7.0
7.0 0 0 0 0 0 0 0 0 0 0 11.0

Sample Output

-2.00 -2.00 -2.00 -2.00 -2.00 -2.00 -2.00 -2.00 -2.00 -2.00 -2.00

solution

练一练高斯消元

为了方便,把n置为11
首先,n维空间两点距离公式为根号下(两点对应值之差的平方的总和)

当然,给了12个点,可以把12个方程先列出来
然后发现方程中有2次项
然而2次项系数为1,相邻两式相减,即可把2次项消掉
然后就是无脑展开,手推公式,转化成高斯消元的形式

这一部分就不讲了,自行手推即可
高斯消元模板也不解释
注:答案会出现-0.00的情况,需要把它加上1e-7

Code:

#include <bits/stdc++.h>
#define maxn 20
#define eps 1e-7
using namespace std;
int n;
double a[maxn][maxn], ans[maxn];

int main(){
	n = 11;
	int M;
	scanf("%d", &M);
	while (M--){
		for (int i = 1; i <= n + 1; ++i)
			for (int j = 1; j <= n + 1; ++j) scanf("%lf", &a[i][j]);
		for (int i = 1; i <= n; ++i){
			a[i][n + 1] = a[i][n + 1] * a[i][n + 1] - a[n + 1][n + 1] * a[n + 1][n + 1];
			for (int j = 1; j <= n; ++j){
				a[i][n + 1] += a[n + 1][j] * a[n + 1][j] - a[i][j] * a[i][j];
				a[i][j] = 2 * (a[n + 1][j] - a[i][j]);
			}
		}
		for (int i = 1; i <= n; ++i){
			int tmp = i;
			for (int j = i + 1; j <= n; ++j)
				if (fabs(a[j][i]) - fabs(a[i][i]) > eps) tmp = j;
			if (tmp != i) swap(a[tmp], a[i]);
			for (int j = i + 1; j <= n; ++j){
				double p = a[j][i] / a[i][i];
				for (int k = i; k <= n + 1; ++k) a[j][k] -= a[i][k] * p;
			}
		}
		ans[n] = a[n][n + 1] / a[n][n];
		for (int i = n - 1; i; --i){
			ans[i] = a[i][n + 1];
			for (int j = i + 1; j <= n; ++j) ans[i] -= a[i][j] * ans[j];
			ans[i] /= a[i][i];
		}
		for (int i = 1; i < n; ++i) printf("%.2lf ", ans[i] + eps); printf("%.2lf\n", ans[n] + eps);
	}
}

BZOJ 1013 球形空间产生器

Description

有一个球形空间产生器能够在n维空间中产生一个坚硬的球体。现在,你被困在了这个n维球体中,你只知道球面上n+1个点的坐标,你需要以最快的速度确定这个n维球体的球心坐标,以便于摧毁这个球形空间产生器。

Input

第一行是一个整数,n。接下来的n+1行,每行有n个实数,表示球面上一点的n维坐标。每一个实数精确到小数点后6位,且其绝对值都不超过20000。

Output

有且只有一行,依次给出球心的n维坐标(n个实数),两个实数之间用一个空格隔开。每个实数精确到小数点后3位。数据保证有解。你的答案必须和标准输出一模一样才能够得分。

Sample Input

2
0.0 0.0
-1.0 1.0
1.0 0.0

Sample Output

0.500 1.500
Hint

数据规模:

对于40%的数据,1<=n<=3

对于100%的数据,1<=n<=10

提示:给出两个定义:

1、 球心:到球面上任意一点距离都相等的点。

2、 距离:设两个n为空间上的点A, B的坐标为(a1, a2, …, an), (b1, b2, …, bn),则AB的距离定义为:dist = sqrt( (a1-b1)^2 + (a2-b2)^2 + … + (an-bn)^2 )

solution

emmm,把上一题的11推广到n
就好了

Code:

#include <bits/stdc++.h>
#define maxn 20
#define eps 1e-7
using namespace std;
int n;
double a[maxn][maxn], ans[maxn];

int main(){
	int n;
	int M = 1;
	while (M--){
		scanf("%d", &n);
		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){
				a[i][n + 1] += a[n + 1][j] * a[n + 1][j] - a[i][j] * a[i][j];
				a[i][j] = 2 * (a[n + 1][j] - a[i][j]);
			}
		}
		for (int i = 1; i <= n; ++i){
			int tmp = i;
			for (int j = i + 1; j <= n; ++j)
				if (fabs(a[j][i]) - fabs(a[i][i]) > eps) tmp = j;
			if (tmp != i) swap(a[tmp], a[i]);
			for (int j = i + 1; j <= n; ++j){
				double p = a[j][i] / a[i][i];
				for (int k = i; k <= n + 1; ++k) a[j][k] -= a[i][k] * p;
			}
		}
		ans[n] = a[n][n + 1] / a[n][n];
		for (int i = n - 1; i; --i){
			ans[i] = a[i][n + 1];
			for (int j = i + 1; j <= n; ++j) ans[i] -= a[i][j] * ans[j];
			ans[i] /= a[i][i];
		}
		for (int i = 1; i < n; ++i) printf("%.3lf ", ans[i] + eps); printf("%.3lf\n", ans[n] + eps);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值