题解 [JSOI2008][LuoguP4035] 球形空间产生器

link

设球心的坐标为 ( x 1 , x 2 , . . . , x n ) (x_1,x_2,...,x_n) (x1,x2,...,xn),可以列出方程:
{ ( a 1 , 1 − x 1 ) 2 + ( a 1 , 2 − x 2 ) 2 + . . . + ( a 1 , n − x n ) 2 = k ( a 2 , 1 − x 1 ) 2 + ( a 2 , 2 − x 2 ) 2 + . . . + ( a 2 , n − x n ) 2 = k . . . ( a n + 1 , 1 − x 1 ) 2 + ( a n + 1 , 2 − x 2 ) 2 + . . . + ( a n + 1 , n − x n ) 2 = k \begin{cases} (a_{1,1}-x_1)^2+(a_{1,2}-x_2)^2+...+(a_{1,n}-x_n)^2=k\\ (a_{2,1}-x_1)^2+(a_{2,2}-x_2)^2+...+(a_{2,n}-x_n)^2=k\\ ...\\ (a_{n+1,1}-x_1)^2+(a_{n+1,2}-x_2)^2+...+(a_{n+1,n}-x_n)^2=k \end{cases} (a1,1x1)2+(a1,2x2)2+...+(a1,nxn)2=k(a2,1x1)2+(a2,2x2)2+...+(a2,nxn)2=k...(an+1,1x1)2+(an+1,2x2)2+...+(an+1,nxn)2=k

是个二次方程,还有个 k k k,不太可解。把方程展开得:
{ ( x 1 2 + x 2 2 + . . . + x n 2 ) − 2 ( x 1 a 1 , 1 + x 2 a 1 , 2 + . . . + x n a 1 , n ) + ( a 1 , 1 2 + a 1 , 2 2 + . . . + a 1 , n 2 ) = k ( x 1 2 + x 2 2 + . . . + x n 2 ) − 2 ( x 1 a 2 , 1 + x 2 a 2 , 2 + . . . + x n a 2 , n ) + ( a 2 , 1 2 + a 2 , 2 2 + . . . + a 2 , n 2 ) = k . . . ( x 1 2 + x 2 2 + . . . + x n 2 ) − 2 ( x 1 a n + 1 , 1 + x 2 a n + 1 , 2 + . . . + x n a n + 1 , n ) + ( a n + 1 , 1 2 + a n + 1 , 2 2 + . . . + a n + 1 , n 2 ) = k \begin{cases} ({x_1}^2+{x_2}^2+...+{x_n}^2)-2(x_1a_{1,1}+x_2a_{1,2}+...+x_na_{1,n})+({a_{1,1}}^2+{a_{1,2}}^2+...+{a_{1,n}}^2)=k\\ ({x_1}^2+{x_2}^2+...+{x_n}^2)-2(x_1a_{2,1}+x_2a_{2,2}+...+x_na_{2,n})+({a_{2,1}}^2+{a_{2,2}}^2+...+{a_{2,n}}^2)=k\\ ...\\ ({x_1}^2+{x_2}^2+...+{x_n}^2)-2(x_1a_{n+1,1}+x_2a_{n+1,2}+...+x_na_{n+1,n})+({a_{n+1,1}}^2+{a_{n+1,2}}^2+...+{a_{n+1,n}}^2)=k\\ \end{cases} (x12+x22+...+xn2)2(x1a1,1+x2a1,2+...+xna1,n)+(a1,12+a1,22+...+a1,n2)=k(x12+x22+...+xn2)2(x1a2,1+x2a2,2+...+xna2,n)+(a2,12+a2,22+...+a2,n2)=k...(x12+x22+...+xn2)2(x1an+1,1+x2an+1,2+...+xnan+1,n)+(an+1,12+an+1,22+...+an+1,n2)=k

K i = [ ( a i , 1 2 + a i , 2 2 + . . . + a i , n 2 ) − ( a i + 1 , 1 2 + a i + 1 , 2 2 + . . . + a i + 1 , n 2 ) ] ÷ 2 K_i=[({a_{i,1}}^2+{a_{i,2}}^2+...+{a_{i,n}}^2)-({a_{i+1,1}}^2+{a_{i+1,2}}^2+...+{a_{i+1,n}}^2)]\div2 Ki=[(ai,12+ai,22+...+ai,n2)(ai+1,12+ai+1,22+...+ai+1,n2)]÷2
n + 1 n+1 n+1 个方程,两两相减可得:
{ x 1 ( a 1 , 1 − a 2 , 1 ) + x 2 ( a 1 , 2 − a 2 , 2 ) + . . . + x n ( a 1 , n − a 2 , n ) = K 1 x 1 ( a 2 , 1 − a 3 , 1 ) + x 2 ( a 2 , 2 − a 3 , 2 ) + . . . + x n ( a 2 , n − a 3 , n ) = K 2 . . . x 1 ( a n , 1 − a n + 1 , 1 ) + x 2 ( a n , 2 − a n + 1 , 2 ) + . . . + x n ( a n , n − a n + 1 , n ) = K n \begin{cases} x_1(a_{1,1}-a_{2,1})+x_2(a_{1,2}-a_{2,2})+...+x_n(a_{1,n}-a_{2,n})=K_1\\ x_1(a_{2,1}-a_{3,1})+x_2(a_{2,2}-a_{3,2})+...+x_n(a_{2,n}-a_{3,n})=K_2\\ ...\\ x_1(a_{n,1}-a_{n+1,1})+x_2(a_{n,2}-a_{n+1,2})+...+x_n(a_{n,n}-a_{n+1,n})=K_n\\ \end{cases} x1(a1,1a2,1)+x2(a1,2a2,2)+...+xn(a1,na2,n)=K1x1(a2,1a3,1)+x2(a2,2a3,2)+...+xn(a2,na3,n)=K2...x1(an,1an+1,1)+x2(an,2an+1,2)+...+xn(an,nan+1,n)=Kn

用高斯消元求解。高斯消元可见:我的文章

//P4035
#include <bits/stdc++.h>
using namespace std;

const double eps = 1e-6;
const int N = 15;
double a[N][N], mat[N][N], sum[N];
int n; 

int gauss(){
	int c, r;//c列,r行 
	for(c = 0, r = 0; c < n; ++ c){
		int tmp = r;
		//找到绝对值最大的行,为了把 0 的行移到最下面去不管它,最后判断 
		for(int i = r; i < n; ++ i) if(fabs(mat[i][c]) > fabs(mat[tmp][c])) tmp = i;
		if(fabs(mat[tmp][c]) < eps) continue;
		for(int i = c; i <= n; ++ i) swap(mat[tmp][i], mat[r][i]);
		for(int i = n; i >= c; -- i) mat[r][i] /= mat[r][c];
		for(int i = r+1; i < n; ++ i) if(fabs(mat[i][c]) > eps)
			for(int j = n; j >= c; -- j) mat[i][j] -= mat[r][j] * mat[i][c];
		++ r;
	}
	if(r < n){
		for(int i = r; i < n; ++ i) if(fabs(mat[i][n]) > eps) return 2;//no solution
		return 1;//infinity
	}	
	for(int i = n-1; i>=0; -- i) for(int j = i+1; j < n; ++ j) mat[i][n] -= mat[i][j] * mat[j][n];
	return 0;
}

int main(){
	scanf("%d", &n);
	
	for(int i = 0; i <= n; ++ i)
		for(int j = 0; j < n; ++ j)
			scanf("%lf", &a[i][j]), sum[i] += a[i][j]*a[i][j];

	for(int i = 0; i < n; ++ i)
		for(int j = 0; j < n; ++ j)
			mat[i][j] = (a[i][j] - a[i+1][j])*2;
	for(int i = 0; i < n; ++ i)
		mat[i][n] = (sum[i] - sum[i+1]);
	gauss();
	
	for(int i = 0; i < n; ++ i)
		printf("%.3lf ", mat[i][n]);
	return 0;
}

当然这题还可以用模拟退火解,这里就不再讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值