zoukankan      html  css  js  c++  java
  • hdu 4606 简单计算几何+floyd+最小路径覆盖

    思路:将所有的直线的两个端点和城市混在一起,将能直接到达的两个点连线,求一次floyd最短路径。二分枚举bag容量,然后按给的要先后占领的城市由前向后,把能到一步到达的建一条边。然后求一次最小路径覆盖,就是最少需要多少个士兵才能全部占领,跟给出的p值进行比较。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define Maxn 510
    #define Maxm Maxn*Maxn
    #define eps 1e-6
    #define inf 100000000
    using namespace std;
    int match[Maxn],vi[Maxn],graphic[Maxn][Maxn],n,m,p,list[Maxn];
    double dis[Maxn][Maxn];
    struct Point{
        double x,y;
    }city[Maxn*10];
    struct Edge{
        Point a,b;
    }edge[Maxn];
    void init()
    {
        int i,j;
        memset(vi,0,sizeof(vi));
        memset(match,-1,sizeof(match));
        memset(graphic,0,sizeof(graphic));
        for(i=1;i<=500;i++)
            for(j=1;j<=500;j++)
            dis[i][j]=inf;
    }
    double multi(Point p0, Point p1, Point p2)//j计算差乘
    {   return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}
    double Dis(Point &a,Point &b)
    { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    bool is_cross(Point s1,Point e1,Point s2,Point e2)//判断线段是否相交(非规范相交)
    {
       return
              multi(s1,e1,s2)*multi(s1,e1,e2) < -eps &&
              multi(s2,e2,s1)*multi(s2,e2,e1) < -eps;
    }
    int dfs(int u)
    {
        int i,j;
        for(i=1;i<=n;i++)
        {
            if(!vi[i]&&graphic[u][i])
            {
                vi[i]=1;
                if(match[i]==-1||dfs(match[i]))
                {
                    match[i]=u;
                    return 1;
                }
            }
        }
        return 0;
    }
    int maxmatch()
    {
        int i,j;
        int ans=0;
        memset(match,-1,sizeof(match));
        for(i=1;i<=n;i++)
        {
            memset(vi,0,sizeof(vi));
            if(dfs(i))
                ans++;
        }
        return n-ans;
    }
    int main()
    {
        int t,i,j,e,k;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&m,&p);
            init();
            for(i=1;i<=n;i++)
                scanf("%lf %lf",&city[i].x,&city[i].y);
            e=n;
            for(i=1;i<=m;i++)
            {
                scanf("%lf%lf%lf%lf",&edge[i].a.x,&edge[i].a.y,&edge[i].b.x,&edge[i].b.y);
                city[++e].x=edge[i].a.x,city[e].y=edge[i].a.y;city[++e].x=edge[i].b.x,city[e].y=edge[i].b.y;
            }
            for(i=1;i<=n;i++)
                scanf("%d",list+i);
            int flag=0;
            for(i=1;i<e;i++)//将能直线到达的点建边
            {
                for(j=i+1;j<=e;j++)
                {
                    flag=0;
                    for(k=1;k<=m;k++)
                    {
                        if(is_cross(city[i],city[j],edge[k].a,edge[k].b))
                           {
                               flag=1;
                               break;
                           }
                    }
                    if(!flag)
                    dis[i][j]=dis[j][i]=Dis(city[i],city[j]);
                }
            }
            double Max=0;
            for(k=1;k<=e;k++)//求所有点的最短路径
                for(i=1;i<=e;i++)
                for(j=1;j<=e;j++)
                {
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
                }
            for(i=1;i<=n;i++)
                for(j=1;j<=n;j++)
                if(dis[i][j]!=inf)
                Max=max(Max,dis[i][j]);
            double l,r,mid;
            l=0,r=Max;
            int temp;
            while(r-l>eps)//二分枚举bag容量
            {
                mid=(l+r)/2;
                memset(graphic,0,sizeof(graphic));
                for(i=1;i<n;i++)
                    for(j=i+1;j<=n;j++)
                    {
                        if(dis[list[i]][list[j]]<=mid)
                        {
                            graphic[list[i]][list[j]]=1;
                        }
                    }
                temp=maxmatch();
                if(temp>p)
                    l=mid;
                else
                    r=mid;
            }
            printf("%.2lf
    ",r);
        }
        return 0;
    }
  • 相关阅读:
    杭电 Problem
    杭电Problem 5053 the sum of cube 【数学公式】
    杭电 Problem 2089 不要62 【打表】
    杭电 Problem 4548 美素数【打表】
    杭电 Problem 2008 分拆素数和 【打表】
    杭电 Problem 1722 Cake 【gcd】
    杭电 Problem 2187 悼念512汶川大地震遇难同胞——老人是真饿了【贪心】
    杭电Problem 1872 稳定排序
    杭电 Problem 1753 大明A+B
    东北林业大 564 汉诺塔
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3213628.html
Copyright © 2011-2022 走看看