思路:将所有的直线的两个端点和城市混在一起,将能直接到达的两个点连线,求一次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*];
struct Edge{
Point a,b;
}edge[Maxn];
void init()
{
int i,j;
memset(vi,,sizeof(vi));
memset(match,-,sizeof(match));
memset(graphic,,sizeof(graphic));
for(i=;i<=;i++)
for(j=;j<=;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=;i<=n;i++)
{
if(!vi[i]&&graphic[u][i])
{
vi[i]=;
if(match[i]==-||dfs(match[i]))
{
match[i]=u;
return ;
}
}
}
return ;
}
int maxmatch()
{
int i,j;
int ans=;
memset(match,-,sizeof(match));
for(i=;i<=n;i++)
{
memset(vi,,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=;i<=n;i++)
scanf("%lf %lf",&city[i].x,&city[i].y);
e=n;
for(i=;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=;i<=n;i++)
scanf("%d",list+i);
int flag=;
for(i=;i<e;i++)//将能直线到达的点建边
{
for(j=i+;j<=e;j++)
{
flag=;
for(k=;k<=m;k++)
{
if(is_cross(city[i],city[j],edge[k].a,edge[k].b))
{
flag=;
break;
}
}
if(!flag)
dis[i][j]=dis[j][i]=Dis(city[i],city[j]);
}
}
double Max=;
for(k=;k<=e;k++)//求所有点的最短路径
for(i=;i<=e;i++)
for(j=;j<=e;j++)
{
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
for(i=;i<=n;i++)
for(j=;j<=n;j++)
if(dis[i][j]!=inf)
Max=max(Max,dis[i][j]);
double l,r,mid;
l=,r=Max;
int temp;
while(r-l>eps)//二分枚举bag容量
{
mid=(l+r)/;
memset(graphic,,sizeof(graphic));
for(i=;i<n;i++)
for(j=i+;j<=n;j++)
{
if(dis[list[i]][list[j]]<=mid)
{
graphic[list[i]][list[j]]=;
}
}
temp=maxmatch();
if(temp>p)
l=mid;
else
r=mid;
}
printf("%.2lf\n",r);
}
return ;
}

最新文章

  1. Mosquitto搭建Android推送服务(二)Mosquitto简介及搭建
  2. java数据结构_笔记(5)_图的算法
  3. 孙鑫MFC学习笔记5:文本显示
  4. Servlet、Filter 生命周期
  5. 转载 C#中敏捷开发规范
  6. 学c语言做练习之​统计文件中字符的个数
  7. 如何知道 win10 的激活到期时间和期限等
  8. mysql主从同步配置(windows环境)
  9. cf734 E. Anton and Tree
  10. JSON.parse()与JSON.stringify()的区别
  11. mysql导出数据至指定文件的命令
  12. 边做边学入门微信小程序之仿豆瓣评分
  13. C语言——第十四、十五周作业
  14. C#/VB.NET 给Word文档添加/撤销书签
  15. linux下的启停脚本
  16. Intellij IDEA环境配置RestEasy,SpringMVC+RestEasy
  17. Flv的结构分析
  18. Yii2 环境配置生产环境和测试环境
  19. JavaScript-2.内置对象---简单脚本之弹出对话框显示当前时间 ---ShinePans
  20. RobotFramework自动化4-批量操作案例

热门文章

  1. POJ 1308 Is It A Tree? (并查集)
  2. [iOS 多线程 &amp; 网络 - 2.9] - ASI框架
  3. Javascript/Jquery——简单定时器的多种实现方法
  4. Google中rel=&quot;canonical&quot;的相关解释和用法
  5. HDU 3668 Volume (数学,积分)
  6. 浅析网站开发中的 meta 标签的作用
  7. sql server2008添加登录账户配置权限 &amp;&amp; 登录时18456错误
  8. 一个简单的hibernate项目
  9. SSH三大框架整合使用的配置文件 注解实现
  10. DataGridView单元格合并