http://acm.hdu.edu.cn/showproblem.php?pid=4606

两点之间如果有线段相隔的话,他们的最短路就需要经过线段的端点

把所有线段的端点也加入点数组中,求任意两个点的距离(可达的话,没有其他线段阻挡)

然后对所有的点进行floyd  可以求出任意两点的最短路

然后二分所需容量 根据容量和要求的顺序进行建图,求最小覆盖路径(匈牙利算法)

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<algorithm>
#include<queue>
#include<stdexcept>
#include<bitset>
#include<cassert>
#include<deque>
#include<numeric> //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll;
typedef unsigned int uint;
typedef pair<int,int> pp;
const double eps=1e-9;
const int INF=0x3f3f3f3f;
const ll MOD=1000000007;
const int N=510;
double x[N],y[N];
double dist[N][N];
int schedule[N];
bool visited[N];
bool link[N][N];
int f[N];
int lr(double x1,double y1,double x2,double y2)
{
double tmp=x1*y2-x2*y1;
if(abs(tmp)<eps)
return 0;
if(tmp>=eps)
return 1;
return -1;
}
bool dfs(int x,int n)
{
for(int i=x+1;i<=n;++i)
if(link[x][i]&&!visited[i])
{
visited[i]=true;
if(f[i]==-1||dfs(f[i],n))
{
f[i]=x;
return true;
}
}
return false;
}
int needSoldier(int n,double d)
{
memset(link,false,sizeof(link));
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j)
if(d-dist[schedule[i]][schedule[j]]>=eps)
link[i][j]=true;
memset(f,-1,sizeof(f));
int sum=0;
for(int i=1;i<=n;++i)
{
memset(visited,false,sizeof(visited));
if(dfs(i,n))
++sum;
}
return (n-sum);
}
double bar(int l,int r,int n,int ln)
{
for(int i=n+1;i<=ln;i=i+2)
{
double x1=x[r]-x[l];
double y1=y[r]-y[l];
double x2=x[i]-x[l];
double y2=y[i]-y[l];
int k1=lr(x1,y1,x2,y2);
x2=x[i+1]-x[l];
y2=y[i+1]-y[l];
int k2=lr(x1,y1,x2,y2);
if(k1==0||k2==0||k1==k2)
continue;
x1=x[i+1]-x[i];
y1=y[i+1]-y[i];
x2=x[l]-x[i];
y2=y[l]-y[i];
k1=lr(x1,y1,x2,y2);
x2=x[r]-x[i];
y2=y[r]-y[i];
k2=lr(x1,y1,x2,y2);
if(k1==0||k2==0||k1==k2)
continue;
return INF;
}
return sqrt((x[r]-x[l])*(x[r]-x[l])+(y[r]-y[l])*(y[r]-y[l]));
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("1007.in","r",stdin);
//freopen("my.out","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
int n,m,p;
scanf("%d %d %d",&n,&m,&p);
for(int i=1;i<=n;++i)
scanf("%lf %lf",&x[i],&y[i]);
int ln=n;
while(m--)
{
++ln;
scanf("%lf %lf",&x[ln],&y[ln]);
++ln;
scanf("%lf %lf",&x[ln],&y[ln]);
}
for(int i=1;i<=n;++i)
scanf("%d",&schedule[i]);
for(int i=1;i<=ln;++i)
for(int j=i;j<=ln;++j)
{
if(i==j) dist[i][j]=0.0;
else
dist[i][j]=dist[j][i]=bar(i,j,n,ln);
}
for(int l=1;l<=ln;++l)
for(int i=1;i<=ln;++i)
for(int j=1;j<=ln;++j)
if(dist[i][j]>dist[i][l]+dist[l][j])
dist[i][j]=dist[i][l]+dist[l][j];
/*
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
cout<<dist[i][j]<<" ";cout<<endl;
}*/
double l=0.0,r=1000000.0;
double ep=1e-6;
while(abs(r-l)>ep)
{
double mid=(l+r)/2;
if(needSoldier(n,mid)<=p)
r=mid;
else
l=mid;
}
printf("%.2lf\n",r);
}
return 0;
}

hdu 4606 Occupy Cities的更多相关文章

  1. HDU 4606 Occupy Cities (计算几何+最短路+二分+最小路径覆盖)

    Occupy Cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  2. HDU 4606 Occupy Cities (计算几何+最短路+最小路径覆盖)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题目:给出n个城市需要去占领,有m条线段是障碍物, ...

  3. HDU 4606 Occupy Cities ★(线段相交+二分+Floyd+最小路径覆盖)

    题意 有n个城市,m个边界线,p名士兵.现在士兵要按一定顺序攻占城市,但从一个城市到另一个城市的过程中不能穿过边界线.士兵有一个容量为K的背包装粮食,士兵到达一个城市可以选择攻占城市或者只是路过,如果 ...

  4. Occupy Cities

    hdu4606:http://acm.hdu.edu.cn/showproblem.php?pid=4606 题意:在一个二维坐标系中,有n个城市,坐标给出来了,然后有p个士兵要去占领这n个城市,但是 ...

  5. hdu 4606 简单计算几何+floyd+最小路径覆盖

    思路:将所有的直线的两个端点和城市混在一起,将能直接到达的两个点连线,求一次floyd最短路径.二分枚举bag容量,然后按给的要先后占领的城市由前向后,把能到一步到达的建一条边.然后求一次最小路径覆盖 ...

  6. hdu 2874Connections between cities LCA

    题目链接 给n个城市, m条边, q个询问, 每个询问, 输出城市a和b的最短距离, 如果不联通, 输出not connected. 用并查集判联通, 如果不连通, 那么两个联通块之间加一条权值很大的 ...

  7. 【 2013 Multi-University Training Contest 1 】

    HDU 4602 Partition f[i]表示和为i的方案数.已知f[i]=2i-1. dp[i]表示和为i,k有多少个.那么dp[i]=dp[1]+dp[2]+...+dp[i-1]+f[i-k ...

  8. hdu 3371 Connect the Cities(最小生成树)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3371 984ms风险飘过~~~ /************************************ ...

  9. 2013 Multi-University Training Contest 1

    HDU-4605 Magic Ball Game 题意:给定一颗以1为根的数,每个节点要么有两个孩子节点,要么没有孩子,每个节点有一个重量,现在从节点1往下放置一个小球,根据小球和节点的重量的不同球落 ...

随机推荐

  1. mysql 查询执行的流程

    1.客户端发送一个请求给服务器.2.服务器先检查查询缓存,命中了缓存,直接返回缓存中的数据,否则进入下一个阶段.3.服务器进行sql解析,预处理,再由优化器生成对应的执行计划.4.mysql根据执行计 ...

  2. 在SSH框架中使用Spring的好处

    在SSH框假中spring充当了管理容器的角色.我们都知道Hibernate用来做持久层,因为它将JDBC做了一个良好的封装,程序员在与数据库进行交互时可以不用书写大量的SQL语句.Struts是用来 ...

  3. Android AIDL Service

    AIDL Service //跨进程调用Service    一个APK想调用另一个APK中的Service 如何实现AIDL //定义两个进程之间的通信接口 Demo1 传递简单数据 AidlSer ...

  4. ref、out

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ref_ ...

  5. Android_开发工具的下载和开发环境的搭建

    一.Android开发工具的下载  Android开发者官网: http://developer.android.com/           Android开发工具:http://www.andro ...

  6. 自定义view获取宽高

    View在构造函数初始化并未布局处理,此时宽高均为0,待所有控件初始化完毕后,由上级容器对内部各控件进行布局,此时控件才会具有位置与大小属性,可以通过以下方法获取:1.在ondraw()函数中获取,2 ...

  7. python操作mongodb之二聚合查询

    #聚合查询 from pymongo import MongoClient db = MongoClient('mongodb://10.0.0.9:27017/').aggregation_exam ...

  8. php 执行外部命令exec() system() passthru()

    php 执行部命令exec() system() passthru() 通常用c写一个外部小程序,然后使用上述命令可以在php中调用 1. exec() string exec ( string $c ...

  9. Linux远程管理

    若想要远程管理服务器,对于Windows系统,应该比较容易理解,通过window系统自带的远程桌面客户端即可登录远程服务器,从而实现在本地对远程服务器的管理.然而对于linux服务器来说这种方法就不行 ...

  10. libuv里的几个缺陷

    libuv是node.js使用的基础库,主要包括主循环,文件和网络接口.虽然libuv是为node.js而生的,但它本身是一个独立的库,加上使用简单方便,所以在node.js之外也有不少人使用.最近整 ...