[bsoj1922] 机器蛇

来源:互联网 发布:软件开发语言培训 编辑:程序博客网 时间:2024/06/10 19:36

题目描述

  在未来的某次战争中,我军计划了一次军事行动,目的是劫持敌人的航母。由于这个计划高度保密,你只知道你所负责的一部分:机器蛇的通信网络。计划中要将数百条机器蛇投放到航母的各个角落里。由于航母内部舱室、管线错综复杂,且大部分由金属构成,因此屏蔽效应十分强烈,况且还要考虑敌人的大强度电子干扰,如何保持机器蛇间的联系,成了一大难题。每条机器蛇的战斗位置由作战计划部门制定,将会及时通知你。每条机器蛇上都带有接收、发射系统,可以同时与多条机器蛇通讯。由于整个系统承载的数据量庞大,需要一个固定的通讯网络。情报部门提供了极其详尽的敌方航母图纸,使你对什么地方有屏蔽了如指掌。
  请你设计一个程序,根据以上信息构造通讯网络,要求信息可以在任意两条机器蛇间传递,同时为了避免干扰,通讯网络的总长度要尽可能的短。


输入格式

  第一行是一个整数n(n≤200)表示参战的机器蛇总数。
  以下n行,每行两个整数xi,yi,为第i支机器蛇的战斗位置。
  接下来一行是一个整数m(m≤100)表示航母内部可能产生屏蔽的位置。
  最后m行,每行四个整数ai,bi,ci,di,表示线段(ai,bi)-(ci,di)处可能有屏蔽,也就是说通讯网络不能跨越这条线段。


输出格式

仅一个实数,表示建立的通讯网的最短长度,保留3位小数。如果不能成功建立通讯网,请输出-1.000。


样例数据

样例输入

3
1 3
3 1
5 5
1
0 0 3 3

样例输出

8.944


题目分析

最小生成树
建边时用计算几何判断线段是否相交


源代码

#include<algorithm>#include<iostream>#include<iomanip>#include<cstring>#include<cstdlib>#include<vector>#include<cstdio>#include<cmath>#include<queue>using namespace std;inline const int Get_Int() {    int num=0,bj=1;    char x=getchar();    while(x<'0'||x>'9') {        if(x=='-')bj=-1;        x=getchar();    }    while(x>='0'&&x<='9') {        num=num*10+x-'0';        x=getchar();    }    return num*bj;}struct Vector;struct Point {    double x,y;};double Dist(Point a,Point b) {    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}struct Vector {    double x,y;};Vector operator - (Point a,Point b) {    Vector c;    c.x=b.x-a.x;    c.y=b.y-a.y;    return c;}double Cross(Vector a,Vector b) { //叉积    return a.x*b.y-b.x*a.y;}bool Segment_Intersect(Point A,Point B,Point C,Point D) { //判断两线段是否相交    return (Cross((C-A),(D-A))*Cross((C-B),(D-B))<0)&&(Cross((A-C),(B-C))*Cross((A-D),(B-D))<0);}////////////////const int maxn=50005;struct Edge {    int x,y;    double v;    bool operator < (Edge b) const {        return v<b.v;    }} a[maxn];struct Kruskal {    int n,m,cnt;    double ans;    int father[maxn];    void init(int n,int m) {        this->n=n;        this->m=m;        ans=cnt=0;    }    void AddEdge(int from,int to,double dist) {        a[++cnt].x=from;        a[cnt].y=to;        a[cnt].v=dist;    }    int Get_Father(int x) {        if(father[x]==x)return x;        return father[x]=Get_Father(father[x]);    }    bool main() {        int cnt=0;        sort(a+1,a+m+1);        for(int i=1; i<=n; i++)father[i]=i;        for(int i=1; i<=m; i++) {            int f1=Get_Father(a[i].x),f2=Get_Father(a[i].y);            if(f1!=f2) {                father[f1]=f2;                ans+=a[i].v;                cnt++;                if(cnt==n-1)break;            }        }        if(cnt!=n-1)return false;        return true;    }};////////////////Point P[205],Start[205],End[205];Kruskal krus;int n,m,sum=0;int main() {    n=Get_Int();    for(int i=1; i<=n; i++) {        P[i].x=Get_Int();        P[i].y=Get_Int();    }    m=Get_Int();    for(int i=1; i<=m; i++) {        Start[i].x=Get_Int();        Start[i].y=Get_Int();        End[i].x=Get_Int();        End[i].y=Get_Int();    }    for(int i=1; i<=n; i++)        for(int j=i+1; j<=n; j++) {            int bj=1;            for(int k=1; k<=m; k++)                if(Segment_Intersect(P[i],P[j],Start[k],End[k])) {                    bj=0;                    break;                }            if(bj==0)continue;            sum++;            krus.AddEdge(i,j,Dist(P[i],P[j]));        }    krus.init(n,sum);    if(!krus.main())puts("-1.000");    else printf("%0.3lf\n",krus.ans);    return 0;}

0 0
原创粉丝点击