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/ ...
随机推荐
- APUE 读书笔记 -----孤儿进程与僵尸进程[总结] +数据结构+C
http://www.cnblogs.com/Anker/p/3271773.html
- careercup-数组和字符串1.2
1.2 用C或C++实现void reverse(char *str)函数,即反转一个null结尾的字符串. C++实现代码: #include<iostream> #include< ...
- /bin/bash^M: bad interpreter: 没有那个文件或目录--转载
运行脚本时出现了这样一个错误,打开之后并没有找到所谓的^M,查了之后才知道原来是文件格式的问题,也就是linux和windows之间的不完全兼容...具体细节不管,如果验证: vim test.sh: ...
- ASP.NET+ashx+jQuery动态添加删除表格
aspx: <script src="../script/jquery-1.4.4.min.js" type="text/javascript" lang ...
- [转载]Access to the path '' is denied.解决方案
原文地址:Access to the path '' is denied.解决方案作者:趴着墙等红杏 ccess to the path '路径' is denied.我在网上找了很多资料,最后终于解 ...
- java-字符串学习总结
Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类. String 类相关基础认知: 1.String类是final的,不可被继承.public fin ...
- 使用Druid作为数据源
Druid号称是Java语言中最好的数据库连接池. 1) 可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能 ...
- linq按需查询
将不确定变成确定~LINQ查询两种写法,性能没有影响,优化查询应该是“按需查询” 如果在linq中希望进行一对多的复合查询时,请直接在查询中使用join into,或者使用let 关键字,当然在建立实 ...
- ria service 单元测试
https://blogs.msdn.microsoft.com/kylemc/2011/08/18/unit-testing-a-wcf-ria-domainservice-part-1-the-i ...
- Oracle 11g 新特性(一)-- 虚拟列
数据库版本: Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Oracle11g 增加了虚拟列的新特性, 具体说明如 ...