Occupy Cities
hdu4606:http://acm.hdu.edu.cn/showproblem.php?pid=4606
题意:在一个二维坐标系中,有n个城市,坐标给出来了,然后有p个士兵要去占领这n个城市,但是路上有m个路障,都是线段,士兵不能越过路障前进。
每个士兵都有相同容量大小的一个干粮袋,每到一个城市他就能补充满自己的干粮袋。中途走路时走一个单位长度就消耗一个单位的干粮。
现在问的是这些个干粮袋最小的容量是多少,前提是保证p个士兵能占领完这n个城市,城市被占领顺序也是题目给好的,必须遵守。
题解:这一题是一道很好的综合题。首先一点,就是求出任意两个城市的最短距离。这个也是我今天学到的知识。我们可以把障碍的端点当做2个点,如果城市i和城市j之间没有障碍的话,那么i,j之间的距离就可以直接算出。如果有障碍的话,就只能绕过障碍的端点来求。怎么求呢?只要把端点当做路径上的点就可以了,然后用floyd过一遍即可。这里,要用到判断两条线段是否相交的。然后可以联想到的是最小点覆盖。但是这里的是最小点覆盖小于p都是满足的。所以接下来可以二分枚举长度,找到最小额满足条件的长度。用到二分以及二分图的最大匹配。因为最小点覆盖==点数--二分图的最大匹配。还有一个就序列,这也是要考虑。这里只哎哟我们建图的时候,让前面的序列指向后面的序列就可以了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const double inf=1000000000.0;
int n,m,p;
int seq[],cy[];
double g[][];
bool key[][],visit[];
struct point{
double x,y;
}dian[];
struct Node{
point a;
point b;
}xian[];
double dis(int a,int b){
return sqrt((dian[a].x-dian[b].x)*(dian[a].x-dian[b].x)+(dian[a].y-dian[b].y)*(dian[a].y-dian[b].y)); }
double Cross( point a, point b, point o){
return (a.x - o.x) * (b.y - o.y) - (b.x - o.x) * (a.y - o.y);
}
bool IsIntersect( Node u, Node v){
return (Cross(v.a, u.b, u.a) * Cross(u.b, v.b, u.a) > ) &&
(Cross(u.a, v.b, v.a) * Cross(v.b, u.b, v.a) > ) &&
(max(u.a.x, u.b.x) > min(v.a.x, v.b.x)) &&
(max(v.a.x, v.b.x) > min(u.a.x, u.b.x)) &&
(max(u.a.y, u.b.y) > min(v.a.y, v.b.y)) &&
(max(v.a.y, v.b.y) > min(u.a.y, u.b.y));
} bool judge(int a,int b){
for(int i=;i<=m;i++){
if((a+-n)/==i&&(b+-n)/==i)continue;
Node temp;temp.a=dian[a];temp.b=dian[b];
if(IsIntersect(temp,xian[i]))
return false;
}
return true;
}
int path(int u){
for(int i=;i<=n;i++){
if(!visit[i]&&key[u][i]){
visit[i]=;
if(cy[i]==-||path(cy[i])){
cy[i]=u;
return ;
}
}
}
return ;
}
int maxmatch(){
memset(cy,-,sizeof(cy));
int res=;
for(int i=;i<=n;i++){
memset(visit,,sizeof(visit));
res+=path(i);
}
return res;
}
bool task(double mid){
memset(key,,sizeof(key));
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
if(g[i][j]<=mid&&seq[i]<seq[j])
key[i][j]=;
}
int as=maxmatch();
if(n-as<=p)return true;
else return false;
} double solve(){
double l=,r=inf,ans=;
while(abs(l-r)>0.0000001){
double mid=(l+r)/;
if(task(mid)){
ans=mid;
r=mid;
}
else
l=mid;
}
return ans;
}
int temp;
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
scanf("%d%d%d",&n,&m,&p);
memset(g,,sizeof(g));
for(int i=;i<=n;i++){
scanf("%lf%lf",&dian[i].x,&dian[i].y);
}
for(int i=;i<=m;i++){
scanf("%lf %lf",&xian[i].a.x,&xian[i].a.y);
dian[i*+n-].x=xian[i].a.x;
dian[i*+n-].y=xian[i].a.y;
scanf("%lf %lf",&xian[i].b.x,&xian[i].b.y);
dian[i*+n].x=xian[i].b.x;
dian[i*+n].y=xian[i].b.y;
}
memset(seq,,sizeof(seq));
for(int i=;i<=n;i++){
scanf("%d",&temp);
seq[temp]=i;
}
for(int i=;i<=n+*m;i++){
for(int j=;j<=n+*m;j++){
if(j==i)continue;
if(judge(i,j)){
g[i][j]=dis(i,j);
}
else
g[i][j]=inf;
}
g[i][i]=inf;
}
for(int k=;k<=n+*m;k++)
for(int i=;i<=n+*m;i++)
for(int j=;j<=n+*m;j++)
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
double ans=;
ans=solve();
printf("%.2f\n",ans);
}
}
Occupy Cities的更多相关文章
- HDU 4606 Occupy Cities (计算几何+最短路+二分+最小路径覆盖)
Occupy Cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- hdu 4606 Occupy Cities
http://acm.hdu.edu.cn/showproblem.php?pid=4606 两点之间如果有线段相隔的话,他们的最短路就需要经过线段的端点 把所有线段的端点也加入点数组中,求任意两个点 ...
- HDU 4606 Occupy Cities ★(线段相交+二分+Floyd+最小路径覆盖)
题意 有n个城市,m个边界线,p名士兵.现在士兵要按一定顺序攻占城市,但从一个城市到另一个城市的过程中不能穿过边界线.士兵有一个容量为K的背包装粮食,士兵到达一个城市可以选择攻占城市或者只是路过,如果 ...
- HDU 4606 Occupy Cities (计算几何+最短路+最小路径覆盖)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove 题目:给出n个城市需要去占领,有m条线段是障碍物, ...
- 【 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 ...
- 2013 Multi-University Training Contest 1
HDU-4605 Magic Ball Game 题意:给定一颗以1为根的数,每个节点要么有两个孩子节点,要么没有孩子,每个节点有一个重量,现在从节点1往下放置一个小球,根据小球和节点的重量的不同球落 ...
- Connect the Cities[HDU3371]
Connect the Cities Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- codeforces 613D:Kingdom and its Cities
Description Meanwhile, the kingdom of K is getting ready for the marriage of the King's daughter. Ho ...
- CF449B Jzzhu and Cities (最短路)
CF449B CF450D http://codeforces.com/contest/450/problem/D http://codeforces.com/contest/449/problem/ ...
随机推荐
- oracle17 视图
oracle的视图 介绍 视图是一个虚拟表是一个表,其内容由查询定义,同真实的表一样,视图包含一系列带有名称的列和行数据.但是,视图并不在数据库中以存储的数据值集形式存在(视图不实际存在).行和列数据 ...
- KDB调试内核
http://www.ibm.com/developerworks/cn/linux/l-kdbug/
- Servlet配置文件
<url-pattern>/servlet/demo</url-pattern> 1.以 / 开头, /代表工程路径:(必须要加 / ) 2.以 * 开头,必须加后缀名 /* ...
- register_globals(全局变量注册开关)
register_globals,是php.ini文件里面的一个配置选项,接下来,我们可以通过例程来分析一下,当register_globals = on 与 register_globals = o ...
- 获取DLL的文件路径以及调用DLL的文件路径
如何在DLL中,获取DLL本身的路径以及调用DLL的文件的路径呢?主要通过GetModuleFileName(HMODULEhModule,LPTSTR lpFilename,DWORD nSize) ...
- 各种vpn协议介绍(重点介绍sslvpn的实现方式openvpn)
vpn介绍: VIrtual Private Network 虚拟专用网络哪些用户会用vpn? 公司的远程用户(出差.家里),公司的分支机构.idc机房.企业间.FQ常见vpn协议有哪些? ...
- 获得Radio选中的后面文本框的值
例如: 选中的radio的值在button中显示 代码如下: <!DOCTYPE html> <html lang="en" xmlns="http:/ ...
- 分享:根据svg节点对象类型和路径值转换坐标值
功能用处: 对svg文件的路径节点填充时会使用(相邻两个坐标区域内的四边形的填充颜色不重复). 需要对svg文件中的Path节点或者 Polyline 节点做颜色填充.并且相邻的两个区域之间的颜色不允 ...
- 导出excel的简单方法
excel的操作,最常用的就是导出和导入,废话不多说上代码. 本例使用NPOI实现的,不喜勿喷哈.... /// <summary> /// 导出Excel /// </summar ...
- Angularjs总结(二)过滤器使用
html页面: <table> <thead> <tr> <td class="td">序号</td> <td c ...