2018 ACM-ICPC, Syrian Collegiate Programming Contest I. Rise of the Robots 最小圆覆盖 模板

题目链接:http://codeforces.com/gym/102006/problem/I

 

题意:

       一个机器人要移动n次,每次移动的路径已知,告诉你桌子的大小和机器人的大小,问你不让机器人移动出桌子的初始位置在哪里。

 

做法:

      因为没有完全确定就不说了 留个板子就好、

 

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-6;
const double Pi=acos(-1.0);
const int maxn=255;
struct node{
    double x,y;
    node(){}
    node(double x,double y):x(x),y(y){}
} P[maxn],c;
int n;
typedef node Vector;
int dcmp(double x)
{
    if (fabs(x)<eps) return 0;
    else if (x<0) return -1;
    else return 1;
}
Vector operator + (Vector a, Vector b){
    return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b){
    return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, double p){
    return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, double p){
    return Vector(a.x / p, a.y / p);
}
bool operator == (const node &a, const node &b){
  return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
double Dot(Vector a, Vector b){//内积
    return a.x*b.x + a.y*b.y;
}
double Length(Vector a){//模
    return sqrt(Dot(a, a));
}
double Angle(Vector a, Vector b){//夹角,弧度制
    return acos(Dot(a, b) / Length(a) / Length(b));
}
double Cross(Vector a, Vector b){//外积
    return a.x*b.y - a.y*b.x;
}
Vector Rotate(Vector a, double rad){//逆时针旋转
    return Vector(a.x*cos(rad) - a.y*sin(rad), a.x*sin(rad) + a.y*cos(rad));
}
double Distance(node a, node b){//两点间距离
    return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
double Area(node a, node b, node c){//三角形面积
    return fabs(Cross(b - a, c - a) / 2);
}



double lenth(node a) {return sqrt(Dot(a,a));}

node rotate(node a,double t)    //向量旋转
{
    return node(a.x*cos(t)-a.y*sin(t),a.x*sin(t)+a.y*cos(t));
}

node jiao(node p,node v,node q,node w)
//p+tv
//q+tw
{
    node u=p-q;
    double t=Cross(w,u)/Cross(v,w);
    return p+v*t;
}

node get_c(node a,node b,node c)
{
    node p=(a+b)/2;    //ad中点
    node q=(a+c)/2;    //ac中点
    node v=rotate(b-a,Pi/2.0),w=rotate(c-a,Pi/2.0);   //中垂线的方向向量
    if (dcmp(Cross(v,w))==0)    //平行
    {
        if (dcmp(Length(a-b)+Length(b-c)-Length(a-c))==0)
           return (a+c)/2;
        if (dcmp(Length(b-a)+Length(a-c)-Length(b-c))==0)
           return (b+c)/2;
        if (dcmp(Length(a-c)+Length(c-b)-Length(a-b))==0)
           return (a+b)/2;
    }
    return jiao(p,v,q,w);
}

void min_circular(){
    random_shuffle(P+1,P+n+1);    //随机化
    double r;
    c=P[1],r=0;
    //c 圆心
    //r 半径
    for (int i=2;i<=n;i++)
        if (dcmp(lenth(c-P[i])-r)>0)    //不在圆内
        {
            c=P[i],r=0;
            for (int j=1;j<i;j++)
                if (dcmp(lenth(c-P[j])-r)>0)
                {
                    c=(P[i]+P[j])/2.0;
                    r=lenth(c-P[i]);
                    for (int k=1;k<j;k++)
                        if (dcmp(lenth(c-P[k])-r)>0)
                        {
                            c=get_c(P[i],P[j],P[k]);
                            r=lenth(c-P[i]);
                        }
                }
        }
}
int main(){
    freopen("robots.in","r",stdin);
    int t;
    cin>>t;
    while(t--){
        double R,r,xx,yy;
        scanf("%d%lf%lf",&n,&R,&r);
        P[1]=node(0,0);
        n++;
        for(int i=2;i<=n;i++){
            scanf("%lf%lf",&xx,&yy);
            P[i]=P[i-1]+node(xx,yy);
        }
        min_circular();
        printf("%.8f %.8f\n",-c.x,-c.y);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM-ICPC(国际大学生程序设计竞赛)是一项面向大学生的计算机编程竞赛,涉及算法和数据结构等领域。在比赛中,选手需要解决一系列编程问题,使用合适的算法和数据结构来实现正确和高效的解决方案。 对于整理ACM-ICPC模板,以下是一些建议: 1. 了解比赛要求:首先,你需要了解ACM-ICPC比赛的具体要求和规则。这包括了解比赛所涉及的算法和数据结构,以及题目的类型和难度等。 2. 收集资料:收集与ACM-ICPC相关的资料,包括经典算法和数据结构的实现代码、常见问题的解题思路等。可以参考教材、博客、论文等资源。 3. 整理模板:将收集到的资料整理成模板。可以按照算法和数据结构的分类进行整理,例如排序算法、图算法、字符串算法等。对每个模板,添加必要的注释和示例代码,以便理解和使用。 4. 测试代码:对每个模板编写测试代码,确保它们的正确性和可靠性。可以使用已知的测试用例或自行设计测试用例。 5. 更新与扩充:定期更新和扩充模板,以适应ACM-ICPC比赛中新出现的算法和数据结构。同时,根据自己的经验和理解,对模板进行优化和改进。 6. 练习和复习:在比赛之前,利用整理好的模板进行练习和复习。尝试解决一些经典问题,使用模板中的算法和数据结构进行实现,并进行优化。 希望这些建议对你整理ACM-ICPC模板有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值