题目大意

  有 \(n\) 个 \(n\) 维空间中的球,求这些球的所有公切面。

  保证不会无解或有无穷多组解。

  \(n\leq 10\)

题解

  你可以认为这是一道传统题。

  记公切面为 \(a_1x_1+a_2x_2+\cdots+ a_nx_n=d\),满足 \(\sum_ia_i^2=1\)。

  一个点 \(x_1,x_2,\ldots,x_n\) 到这个面的距离为

\[\frac{\lvert a_1x_1+a_2x_2\cdots +a_nx_n-d\rvert}{\sqrt{a_1^2+a_2^2+\cdots+a_n^2}}
\]

  对于第 \(i\) 个球,有 \(\lvert\sum_{j}a_jx_{i,j}-d\rvert=r\)。

  枚举所有 \(\lvert\sum_{j}a_jx_{i,j}-d\rvert\) 的符号,把绝对值符号去掉。

  然后解方程解出 \(a_i=D_1d+D_2\),带进 \(\sum_ia_i^2=1\) 中解方程就可以解出 \(d\)。

  时间复杂度:\(O(n^32^n)\)。

  直接解方程可能会有奇怪情况,所以要把所有坐标偏移一个值。

代码

const ldb eps=1e-6;
ldb DELTA[]={0,0.235,0.3746,0.1246,0.2153,0.364,0.1253,0.6124,0.164,0.7543,0.35476};
int n;
ldb a[20][20];
ldb r[20];
ldb ans[2100][20][20];
ldb b[20][20];
ldb c[20][20];
ldb e[20];
int cnt;
void gao(ldb d)
{
for(int i=1;i<=n;i++)
e[i]=c[i][n+1]*d+c[i][n+2];
cnt++;
for(int i=1;i<=n;i++)
{
ldb s=0;
for(int j=1;j<=n;j++)
s+=a[i][j]*e[j];
s-=d;
for(int j=1;j<=n;j++)
ans[cnt][i][j]=a[i][j]-s*e[j];
}
}
void calc()
{
memcpy(c,b,sizeof b);
int flag=0;
for(int i=1;i<=n;i++)
{
int x=i;
for(int j=i;j<=n;j++)
if(fabs(c[j][i])>fabs(c[x][i]))
x=j;
if(fabs(c[x][i])<eps)
{
flag=1;
continue;
}
if(x!=i)
swap(c[x],c[i]);
ldb v=1/c[i][i];
for(int j=1;j<=n+2;j++)
c[i][j]*=v;
for(int j=1;j<=n;j++)
if(j!=i)
{
ldb v=c[j][i];
for(int k=1;k<=n+2;k++)
c[j][k]-=c[i][k]*v;
}
}
if(flag)
{
// ldb d;
// for(int i=1;i<=n;i++)
// if(!c[i][i])
// {
// if(flag)
// {
// }
// else
// {
// }
printf("error\n");
return;
}
ldb A=0,B=0,C=0;
for(int i=1;i<=n;i++)
{
A+=c[i][n+1]*c[i][n+1];
B+=2*c[i][n+1]*c[i][n+2];
C+=c[i][n+2]*c[i][n+2];
}
C-=1;
if(fabs(A)<eps)
{
if(fabs(B)<eps)
{
return;
}
ldb d=-C/B;
gao(d);
}
else
{
ldb delta=B*B-4*A*C;
if(delta<-eps)
return;
else
delta=max(delta,(ldb)0);
if(delta<eps)
{
ldb d=-B/(2*A);
gao(d);
}
else
{
ldb d1=(-B+sqrt(delta))/(2*A);
gao(d1);
ldb d2=(-B+sqrt(delta))/(2*A);
gao(d2);
}
}
}
void dfs(int x)
{
if(x>n)
{
calc();
return;
}
for(int i=1;i<=n;i++)
b[x][i]=a[x][i];
b[x][n+1]=1;
b[x][n+2]=r[x];
dfs(x+1);
if(fabs(r[x])<eps)
return;
b[x][n+2]=-r[x];
dfs(x+1);
}
void solve()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%Lf",&a[i][j]);
a[i][j]-=DELTA[j];
}
scanf("%Lf",&r[i]);
}
cnt=0;
dfs(1);
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++)
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
printf("%.20Lf ",ans[i][j][k]+DELTA[k]);
printf("\n");
}
}
int main()
{
// freopen("0.in","r",stdin);
int t;
scanf("%d",&t);
while(t--)
solve();
return 0;
}

【THUSC2017】【LOJ2982】宇宙广播 计算几何 高斯消元的更多相关文章

  1. 【THUSC2017】【LOJ2978】杜老师 高斯消元

    题目大意 给你 \(l,r\),求从 \(l\) 到 \(r\) 这 \(r-l+1\) 个数中能选出多少个不同的子集,满足子集中所有的数的乘积是一个完全平方数. 对 \(998244353\) 取模 ...

  2. 【BZOJ-3143】游走 高斯消元 + 概率期望

    3143: [Hnoi2013]游走 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2264  Solved: 987[Submit][Status] ...

  3. 【BZOJ-3270】博物馆 高斯消元 + 概率期望

    3270: 博物馆 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 292  Solved: 158[Submit][Status][Discuss] ...

  4. *POJ 1222 高斯消元

    EXTENDED LIGHTS OUT Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9612   Accepted: 62 ...

  5. [bzoj1013][JSOI2008][球形空间产生器sphere] (高斯消元)

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

  6. hihoCoder 1196 高斯消元·二

    Description 一个黑白网格,点一次会改变这个以及与其连通的其他方格的颜色,求最少点击次数使得所有全部变成黑色. Sol 高斯消元解异或方程组. 先建立一个方程组. \(x_i\) 表示这个点 ...

  7. BZOJ 2844 albus就是要第一个出场 ——高斯消元 线性基

    [题目分析] 高斯消元求线性基. 题目本身不难,但是两种维护线性基的方法引起了我的思考. void gauss(){ k=n; F(i,1,n){ F(j,i+1,n) if (a[j]>a[i ...

  8. SPOJ HIGH Highways ——Matrix-Tree定理 高斯消元

    [题目分析] Matrix-Tree定理+高斯消元 求矩阵行列式的值,就可以得到生成树的个数. 至于证明,可以去看Vflea King(炸树狂魔)的博客 [代码] #include <cmath ...

  9. UVALive 7138 The Matrix Revolutions(Matrix-Tree + 高斯消元)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

随机推荐

  1. IIS安装以及发布

    控制面板-所有控制面板项-程序和功能-打开或关闭windows功能-Internet 信息服务,里面全部打钩点击确实.安装完成.     控制面板-管理工具-Internet 信息服务管理器-双击打开 ...

  2. Linux基本命令操作

    3.1  Linux终端介绍.Shell提示符.Bash基本语法 3.1.1  登录LINUX终端 两种终端仿真器:1.GNOME桌面的GHOME Terminal : 2.KDE桌面的Konsole ...

  3. Java并发——线程介绍

    前言: 互联网时代已经发展到了现在.从以前只考虑小流量到现在不得不去考虑高并发的问题.扯到了高并发的问题就要扯到线程的问题.你是否问过自己,你真正了解线程吗?还是你只知道一些其他博客里写的使用方法.下 ...

  4. PhP数据库 Mysql dos命令

    mysql 这是一个关系型数据库,存在表的概念. 结构 数据库可以存放多张表,每个表可以存放多个字段,每个字段可以存放多个记录. dos命令操作数据库 phpstudy使用终端打开数据库 第一步: 第 ...

  5. 判断值是否为undefined

    可以使用 Ext.isDefined( value ) 这个函数, 也可以使用下面代码来进行实现: /** 判断传入的值是否 为undefined */ function isUndefined(va ...

  6. Javascript之高级数组API的使用实例

    JS代码中我们可以根据需求新建新的对象解决问题的同时,也有一些常用的内置对象供我们使用,我们称之为API,本篇文章只是对数组部分进行了练习. 例一:伪数组,不能修改长短的数组(所以没办法清零),可以修 ...

  7. 1920*1080pc端适配

    (function(doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? ' ...

  8. java基础(四):谈谈java中的IO流

    1.字节流 1.1.字节输出流output 1.1.1.数据写入文件中 通过api查找output.找到很多,其中java.io.OutputStream,OutputStream: 输出字节流的超类 ...

  9. 1.3 使命的完成者Command

    为什么要从Command说起? 因为Command才是Cesium源码中真正意义的绘制细胞.

  10. ASP.NET学习笔记 —— 一般处理程序之图片上传

    简单图片上传功能目标:实现从本地磁盘读取图片文件,展示到浏览器页面.步骤:(1). 首先创建一个用于上传图片的HTML模板,命名为ImageUpload.html: <!DOCTYPE html ...