题目大意:

  给你n艘宇宙飞船的前三维坐标,给你这些飞船之间的距离,问在至少多少维的空间里才能使这些飞船之间的距离都等于所给的距离。如果在大于等于3维的坐标下不能满足就输出“Goodbye World!”。(距离是K维空间下的欧几里得距离)

思路:

  首先明确一下所求的是飞船所在空间的最小维数,但是这个维数在不知道坐标的情况下是求不出来的。但是如果先求坐标再判断维数,会发现符合题意的坐标有很多个,直接求解解出来的是一个解系,不好直接解。如果暴力判断枚举范围很大,会超时。

  但是根据现代的理解,很容易发现这个解是单调的,也就是说如果假设解是k,那么所有大于等于k的维数都满足题中的距离,然后继续根据现代的理解可以知道,所求的最小维数k一定是在所给的n艘宇宙飞船的坐标(看成向量)相互线性无关的情况下(其中任一个向量不能由其他任一个向量线性组合而成)得到的。那么我们就可以想到,把这些宇宙飞船的坐标正交化必然可以得到一组每个向量都只有一维非零的向量,并且这个操作不改变这组向量所在的空间维数(虽然会让这个解不再符合题目所给的距离,但是不影响,因为不改变最终所求的空间最小维数),然后单位化再经过选择性地交换矩阵的两行必然可以得到一个单位矩阵(其实单位化是没有必要的,这里进行单位化只是为了让读者思路更清晰,最终目标是想得到一个下三角矩阵)。然后必然可以通过重复将矩阵一行乘以k加到,另一行上这个操作得到一个下三角矩阵。也就是说,虽然解有很多个,但是经过一系列操作可以让这个解变成下三角矩阵或者单位矩阵(这个时候可以明显看出所在空间最小维数)。换言之,我们可以直接通过尝试求解“是否存在一个前三维满足题意的n行下三角矩阵使得,这些向量之间的距离满足题意”来判断测试点是否有解。通过求解这个下三角矩阵同时求出维数。

算法:

1、预处理两两宇宙飞船之间的距离(减去前三维的坐标的影响),这样前三维就可以看成0,然后被忽略掉了。这样所求的矩阵(除去前三维的),就彻底成为一个下三角矩阵了。

2、矩阵由宇宙飞船的坐标构成(预处理后忽略前三维),第一行是第一艘宇宙飞船的坐标,第二行是第二艘,如此类推。(当然在进入第三步前,这些坐标都被初始化成0)

3、如果第一艘飞船和第二艘飞船的距离(预处理后的)不为0,固定第一艘飞船的新一维坐标为0(下三角矩阵的上三角必然为0)。通过第一艘飞船和第二艘之间的距离(预处理以后的),列方程解出第二艘飞船新增一维(原来 新增维数 k为0,现在为1)的坐标(其实就是sqrt(d12 ’),顺便记录下新增的第k维是在计算那一艘飞船的时候被新增的add[k] ;如果为0,则不新增维数,或者看成第二艘飞船新增维数对应的坐标值为0,进入下一步。

4、逐一计算第i艘宇宙飞船在新增的维数(k)上的坐标。具体方法是根据第一艘 飞船和第i艘飞船之间的距离,和第add[k]艘飞船之间的距离之间的关系,列一个距离的方程组(所有的k都有一个方程),这个方程组的未知数就是正在计算的这个i飞船的坐标。

代码:

//#pragma GCC optimize(2)
#pragma comment(linker, "/STACK:10240000,10240000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<ctime>
#include<ctype.h>
#include<stdlib.h>
#include<bitset>
#include<algorithm>
#include<assert.h>
#include<numeric> //accumulate
#define endl "\n"
#define fi first
#define se second
#define forn(i,s,t) for(int i=(s);i<=(t);++i)
#define mem(a,b) memset(a,b,sizeof(a))
#define rush() int MYTESTNUM;cin>>MYTESTNUM;while(MYTESTNUM--)
#define debug(x) printf("%d\n",x)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mp make_pair
#define pb push_back
#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define pf(x) printf("%d\n",x)
#define pf2(x,y) printf("%d %d\n",x,y)
#define pf3(x,y,z) printf("%d %d %d"\n,x,y,z)
#define ll unsigned long long
using namespace std;
const double eps=1e-6;//一开始eps=1e-12 WA了
const int maxn=60;
const ll P=1e9+7;
ll mul(ll a, ll b){ll ans = 0;for(;b;a=a*2%P,b>>=1) if(b&1) ans=(ans+a)%P;return ans;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
inline int read()
{int X=0,w=0; char ch=0;while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X;
}
int n;
double a[maxn][maxn];//坐标
double dis[maxn][maxn];//距离
int num[maxn];//第一次增加t维度是在计算第num[t]艘宇宙飞船时
int main()
{rush(){n=read();for(int i=0;i<n;++i)for(int j=0;j<3;++j)a[i][j]=read();//读入坐标bool flag=0;//假设有解for(int i=0;i<n;++i)for(int j=i+1;j<n;++j){dis[i][j]=read();for(int k=0;k<3;++k) dis[i][j]-=(a[i][k]-a[j][k])*(a[i][k]-a[j][k]);if(dis[i][j]<-eps/*这个负号是个坑*/){ flag=1;/*cout<<"At the begining"<<endl;*/}//一个数的平方为负数,说明在本题中无解。dis[j][i]=dis[i][j];//后面如果能一直保证顺序不敲错也可以不写这行
            }if(!flag)//初步判断有解时
        {mem(a,0);mem(num,0);int k=0;//一开始新增的维数为0for(int i=1;i<n;++i){double now=dis[i][0];//第i艘飞船和0艘之间的距离for(int j=0;j<k;++j){if(a[num[j]][j]>eps)//如果大于0就要新增一个维度{/*这里一直在解方程,k元二次方程组,通过手算前几个推出规律*/double sum=0;for(int p=0;p<k+1;++p)sum+=(a[num[j]][p]-a[i][p])*(a[num[j]][p]-a[i][p]);double mid=(sum-dis[i][num[j]]);sum=0;for(int p=0;p<k+1;++p)sum+=(a[0][p]-a[i][p])*(a[0][p]-a[i][p]);double mi=sum-dis[i][0];mid-=mi;a[i][j]=mid/2/a[num[j]][j];//解出这一行的第j个未知数
                    }if(now-a[i][j]*a[i][j] < -eps/*前面WA了一次现在顺手把这个负号也加上*/){flag=1;/*cout<<"105"<<endl;*/break;}//在解下一个未知数前,剩下要算的距离平方已经为负数则无解else now-=(a[i][j])*(a[i][j]);//否则继续算下一个未知数
                }if(flag==1) break;// cout<<"now "<<now<<endl;if(now>eps){/*这里是最后一个未知数,因为循环最后一步已经判断是否大于0了,所有直接开平方解出来就行*/num[k]=i;a[i][k]=sqrt(now);k++;//维数加一
                }//cout<<"now"<<sqrt(now)<<endl;for(int j=0;j<i;++j){/*算的时候,是根据前面所有增加过维数的飞船,加上第一艘飞船和第i艘飞船之间的距离 列出来的方程组算出解的这个解不一定满足那些没有新增维度的飞船给出的距离,所以检查一下*/double sum=0;for(int p=0;p<k+1;++p)sum+=(a[j][p]-a[i][p])*(a[j][p]-a[i][p]);if(fabs(sum-dis[i][j])>eps){flag=1;/*cout<<"116"<<endl;*/break;}}}if(!flag) printf("%d\n",k+3);//最后的答案要加上前3维
        }if(flag) cout<<"Goodbye World!"<<endl;//无解的输出
    }return 0;
}

转载于:https://www.cnblogs.com/LS-Joze/p/11406305.html

K-Dimensional Foil HihoCoder - 1628 线性代数 解方程相关推荐

  1. matlab 解函数方程,MATLAB程序设计教程(7)—MATLAB解方程与函数极值

    MATLAB程序设计教程(7)--MATLAB解方程与函数极值 第7章MATLAB解方程与函数极值 7.1  线性方程组求解 7.2  非线性方程数值求解 7.3  常微分方程初值问题的数值解法 7. ...

  2. matlab解方程教程,MATLAB程序设计教程(7)—MATLAB解方程与函数极值

    第7章 MATLAB解方程与函数极值 7.1 线性方程组求解 7.2 非线性方程数值求解 7.3 常微分方程初值问题的数值解法 7.4 函数极值 7.1 线性方程组求解 7.1.1 直接解法 1.利用 ...

  3. matlab求函数极值教程,MATLAB程序设计教程(7)—MATLAB解方程与函数极值

    MATLAB程序设计教程(7)--MATLAB解方程与函数极值 第7章MATLAB解方程与函数极值 7.1  线性方程组求解 7.2  非线性方程数值求解 7.3  常微分方程初值问题的数值解法 7. ...

  4. 10.24T3 解方程 取模意义下运算+秦九韶算法

    #1228 解方程 描述 已知多项式方程: a0+a1x+a2x^2+..+anx^n=0 求这个方程在[1, m ] 内的整数解(n 和m 均为正整数) 输入 输入共n + 2 行. 第一行包含2 ...

  5. 重根迭代法解方程(两种方法)(Python实现)

    简述 通过两种不同的重根迭代的来解方程. 处理的方程是 (sin(x) - x/2) ^2 = 0 代码 采用的第一种迭代重根迭代方法: xk+1=xk−mf(xk)f′(xk)xk+1=xk−mf( ...

  6. 2017广东工业大学程序设计竞赛决赛 题解源码(A,数学解方程,B,贪心博弈,C,递归,D,水,E,贪心,面试题,F,贪心,枚举,LCA,G,dp,记忆化搜索,H,思维题)...

    心得: 这比赛真的是不要不要的,pending了一下午,也不知道对错,直接做过去就是了,也没有管太多! Problem A: 两只老虎 Description 来,我们先来放松下,听听儿歌,一起&qu ...

  7. 20220401 从解方程角度看什么是线性系统的能控与能观

    目录 1. 能控 1.1 单入多出 1.2 多入多出 2. 能达 3. 能观 4. 总结 1. 能控 1.1 单入多出 线性定常离散系统通常要进行能控和能观的分析,其实,所谓的能控和能观无非就是解方程 ...

  8. 解方程 2014NOIP提高组 (数学)

    解方程  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description 输入描述 Input Description 输入文 ...

  9. HDU - 3364 Lanterns(高斯消元解方程(取模))

    题目链接:点击查看 题目大意:给出 n 盏灯和 m 个开关,每个开关可以控制多个灯,每次询问给定灯的最终状态,问有多少种方案可以到达 题目分析:以开关为变元,灯为方程列出方程组,每次求出有多少个自由元 ...

最新文章

  1. php中使用Curl、socket、file_get_contents三种方法POST提交数据
  2. 10台客户机打印机文件服务器,Sever-U实现局域网打印机安全共享.doc
  3. SAP UI 搜索分页技术
  4. 程序人生:写给新入行程序员职业生涯的10条建议
  5. 基于HubServing的PaddleOCR部署
  6. 第47课 称心如意的输入 《小学生C++趣味编程》
  7. java jar包与配置文件的写法
  8. JSP基础(5)-JSP标准动作
  9. 用gpg加密软件加密文件
  10. 如何查看APP ID
  11. 曾经跨过山和大海的百度AI技术汇,跨进北工大!
  12. 2017-2018 ACM-ICPC, Asia Daejeon Regional Contest H题
  13. [更新1.0:补丁绕过]CVE-2020-14882: Weblogic Console HTTP 远程代码执行漏洞通告
  14. flutter 仿网易云音乐(3)
  15. Multisim 设计任务
  16. jsp网上招标系统毕业设计
  17. MP4文件格式详解——结构概述
  18. UnicodeDecodeError: 'gb18030' codec can't decode byte 0xeb in position 7: incomplete multibyte seque
  19. AD19全局替换网络标号
  20. 北京怎么可以买到既时尚又便宜衣服

热门文章

  1. 【编写可读代码的艺术】读书小记 二: 简化循环和逻辑
  2. linux检测磁盘 报警,linux服务器磁盘监控脚本分享(含报警邮件)
  3. django学习-武沛齐教程【day4】
  4. 08北京奥运会详细赛程提前公布
  5. Extreme Programming (XP)实践
  6. java factorial_Java Factorial Program
  7. QT signals and slots
  8. 美国服务器网站怎么黑屏了,关于美国服务器IP的常见问题的详细解答!
  9. spark编程基础python版 pdf_Spark编程基础Python版-第5章-Spark-SQL.pdf
  10. 辰视冯良炳博士将出席AI+5G+机器视觉赋能智能制造论坛并作主旨演讲