Rescue The Princess 山东省赛题 求三角形顶点 atan2求解

题目链接:http://acm.upc.edu.cn/problem.php?id=2217

一拿到该题,并不知道,有atan2这个函数,所以只能解方程组求解了,结果耗费了大量的时间才写出来,而且代码比较冗长,真是有些蛋疼。下面说说atan2这个函数的用法吧:

atan2(delta y,delta x),感觉应该是这样的一种形式,刚开始以为这是用来求直线的斜率的,但从试用的情况来看,并不是这样,而是用来求向量的倾斜角的:

当向量向上是为正值,当向量向下时为负值。

只要知道了这个结论,那么此题就变得比较容易了,仔细分析给定向量的四种情况,可以得到一个通用求解表达式,见代码。


代码:

#include<iostream>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<string>
#define LL long long
#define INF 0x7fffffff
//freopen("D:\\in.txt","r",stdin);
using namespace std;

double x[3],y[3];

int main(){
    int T;cin>>T;
    while(T--){
        cin>>x[1]>>y[1]>>x[2]>>y[2];
        double t=sqrt(pow(x[1]-x[2],2.0)+pow(y[2]-y[1],2.0));
        double r=atan2(y[2]-y[1],x[2]-x[1]);
        r+=3.1415926535897932384626/3;
        printf("(%.2lf,%.2lf)\n",x[1]+t*cos(r),y[1]+t*sin(r));//四种情况都满足
    }
    return 0;
}

顺便附上我写的数学求解代码(太长了):

#include<iostream>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<string>
#define LL __int64
#define INF 0x7fffffff
//freopen("D:\\in.txt","r",stdin);
using namespace std;

double x[3],y[3],t,p,q,tq,a,b,c,X,Y;

void disp(double s,double delta){
    double ty=(y[1]+y[2])/2;
    for(int i=-1;i<=1;i+=2){
        X=s+i*delta;Y=X*p+q;//由于是二元的,会有不满足条件的解,需要判断,而且还得是逆时针方向
        if(x[1]<x[2] && Y>ty){printf("(%.2lf,%.2lf)\n",X,Y);;return;}
        if(x[1]>x[2] && Y<ty){printf("(%.2lf,%.2lf)\n",X,Y);;return;}
    }
}

void disp2(int n){
    double ans[2];
    for(int i=-1;i<=1;i+=2){
        if(n==1){
            ans[n]=y[1]+i*t*sqrt(3)/2;
            ans[1-n]=(x[1]+x[2])/2;
            if(x[1]<x[2] && ans[n]>y[1]) {
                printf("(%.2lf,%.2lf)\n",ans[0],ans[1]);
                return;
            }
            if(x[1]>x[2] && ans[n]<y[1]){
                printf("(%.2lf,%.2lf)\n",ans[0],ans[1]);
                return;
            }
        }
        else {
            ans[n]=x[1]+i*t*sqrt(3)/2;
            ans[1-n]=(y[1]+y[2])/2;
            if(y[1]>y[2] && ans[n]>x[1]) {
                printf("(%.2lf,%.2lf)\n",ans[0],ans[1]);
                return;
            }
            if(y[1]<y[2] && ans[n]<x[1]){
                printf("(%.2lf,%.2lf)\n",ans[0],ans[1]);
                return;
            }
        }
    }
}

int main(){
    int T;cin>>T;
    while(T--){
        cin>>x[1]>>y[1]>>x[2]>>y[2];
        t=sqrt((x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2]));
        if(x[1]==x[2]) {disp2(0);continue;}//斜率为0和90度时单独求解
        if(y[1]==y[2]){disp2(1);continue;}
        p=(x[2]-x[1])/(y[1]-y[2]);//否则利用方程组求出第三点的解
        q=(x[1]*x[1]-x[2]*x[2]+y[1]*y[1]-y[2]*y[2])/(2*(y[1]-y[2]));
        tq=q-y[1];
        a=1+p*p;b=2*(p*tq-x[1]);c=x[1]*x[1]+tq*tq-t*t;
        double delta=sqrt(b*b-4*a*c)/(2*a),s=-1*b/(2*a);
        disp(s,delta);
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值