2 2 1 1 0 0 2 0 1 1 1 -1 2 1 4 2 2 0 1 5 1 8 0 1 -1 0 0 2 0 6 0 6 3 1 2 3 4
2.83 3.41HintFor the second sample case, the best strategy is: step 1: air-drop soldier 1 to city 1, city 1 occupied; step 2: air-drop soldier 2 to city 2, city 2 occupied; step 3: soldier 2 moves from city 2 to city 3, city 3 occupied, and 3.41 units of food needed; step 4: soldier 1 moves from city 1 to city 4, city 4 occupied, and 2.41 units food needed. Therefore, the minimal volume of bags is 3.41.
题意:有n个城市,然后有p个士兵要去占领,路上有m个路障,都是线段,士兵
不能越过路障前进。每个士兵都有相同容量大小的一个干粮袋,每到一个城市他
就能补充满自己的干粮袋。中途走路时走一个单位长度就消耗一个单位的干粮。
现在问的是这些个干粮袋最小的容量是多少,前提是保证p个士兵能占领完这n个
城市,城市被占领顺序也是题目给好的,必须遵守。
思路:P个士兵占领n个城市,可以看成p个士兵走出了p个路径,覆盖了所有的点。
最小路径覆盖的要求之一就是有向,无环,在题目中的体现就是城市被占领时必须
有顺序。然后枚举所有顶点,求一下距离,判断是否与线段相交。然后 floyd预处
理最短路,之后是二分答案,判断是否可达根据占领的先后顺序建边,根据二分
的值判断不需要补给是否能够到达。判断条件为最小路径覆盖数是否小于等于P。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const double eps=1e-7;
const double inf=999999999;
const int maxn=310;
struct point
{
    double x,y;
    point() {}
    point(double _x,double _y):x(_x),y(_y) {}
    friend point operator - (const point &p,const point &q)
    {
        return point(p.x-q.x,p.y-q.y);
    }
    friend bool operator == (const point &p,const point &q)
    {
        if(fabs(p.x-q.x)<eps && fabs(p.y-q.y)<eps) return true;
        return false;
    }
} A[maxn],B[maxn],C[maxn];
int n,m,p,cnt,a[maxn],match[maxn];
double dis[maxn][maxn];
bool con[maxn][maxn],visited[maxn];
double dcheng(point p,point q)
{
    return (p.x*q.y-p.y*q.x);
}
bool cross(point x1,point y1,point x2,point y2)
{
    double t1=dcheng(y1-x1,x2-x1);
    double t2=dcheng(y1-x1,y2-x1);
    double t3=dcheng(y2-x2,x1-x2);
    double t4=dcheng(y2-x2,y1-x2);
    if(t1*t2<0 && t3*t4<0)  return true;
    return false;
}
double dist(point p,point q)
{
    return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}
void initial()
{
    for(int i=0; i<maxn; i++)
        for(int j=0; j<maxn; j++)
           {
               if(i==j)  dis[i][j]=0;
               else  dis[i][j]=inf;
           }
}
void input()
{
    scanf("%d %d %d",&n,&m,&p);
    cnt=n;
    for(int i=1; i<=n; i++)   scanf("%lf %lf",&A[i].x,&A[i].y);
    for(int i=0; i<m; i++)
    {
        scanf("%lf %lf %lf %lf",&B[i].x,&B[i].y,&C[i].x,&C[i].y);
        A[++cnt]=B[i];
        A[++cnt]=C[i];
    }
    for(int i=0; i<n; i++)    scanf("%d",&a[i]);
}
void ready()
{
    for(int i=1; i<=cnt; i++)
        for(int j=i+1; j<=cnt; j++)
        {
            bool flag=1;
            for(int k=0; k<m; k++)
            {
                if((A[i]==B[k] && A[j]==C[k]) || (A[i]==C[k] && A[j]==B[k])) continue;
                if(cross(A[i],A[j],B[k],C[k]))
                {
                    flag=0;
                    break;
                }
            }
            if(flag)  dis[i][j]=dis[j][i]=dist(A[i],A[j]);
        }
}
void floyd()
{
    for(int k=1;k<=cnt;k++)
        for(int i=1;i<=cnt;i++)
           for(int j=1;j<=cnt;j++)
               dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
void build(double r)
{
    memset(con,0,sizeof(con));
    memset(match,-1,sizeof(match));
    for(int i=0;i<n;i++)
        for(int j=i+1;j<n;j++)
         {
              double t=dis[a[i]][a[j]];
              if(t<r || fabs(t-r)<eps)  con[a[i]][a[j]]=1;
         }
}
bool dfs(int x)
{
    for(int i=1;i<=n;i++)
    {
        if(con[x][i] && !visited[i])
        {
            visited[i]=1;
            if(dfs(match[i]) || match[i]==-1)
            {
                 match[i]=x;
                 return true;
            }
        }
    }
    return false;
}
bool judge()
{
    int ret=0;
    for(int i=1;i<=n;i++)
    {
        memset(visited,0,sizeof(visited));
        if(dfs(i))  ret++;
    }
    if(n-ret<=p)  return true;
    return false;
}
void solve()
{
    floyd();
    double l=0.0,r=inf;
    while(l+eps<r)
    {
        double mid=(l+r)/2;
        build(mid);
        if(judge()) r=mid;
        else l=mid;
    }
    printf("%.2lf\n",r);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        initial();
        input();
        ready();
        solve();
    }
    return 0;
}
hdu 4606 Occupy Cities(线段相交+最小路径覆盖+二分)
原文:http://blog.csdn.net/u012596172/article/details/43054087