题面

养鸽人要监视他的鸽子,有n只鸽子站在平面上,他可以在m个给定的点上设置监视器,如果一只鸽子在某个监视器上或者在两个监视器所连直线上或者在三个监视器所连直线的三角形内则其就咕咕咕了,现在养鸽人要让所有鸽子咕咕咕,请问他最少需要设置多少监视器。

对于100%的数据n≤100000,m≤500,坐标绝对值不超过10的9次方。

100

首先转化一下题意,就是选取尽量少的点,然后生成一个凸包,包住给定的一个凸包。

显然在给定凸包内的点是没有用处的。

对于不在给定凸包内的点,我们枚举它们:

对于一个点i,找出其与给定凸包的两条“切线”。



如图,两条切线即为x,y,那么就有使\(i\)给图中蓝色的点连一条长度为1的边。

由于凸包是,一个点出发,回到这个点的最短路。

然后做一遍floyd就可以了。

Code

#include<bits/stdc++.h>
#define ll long long
#define db double
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define fd(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
const int inf=0x7fffffff;
const char* fin="pigeon.in";
const char* fout="pigeon.out";
const int maxn=100007,maxm=507;
const db eps=1e-10;
int equ(db v,db c){return (fabs(v-c)<eps?0:(v<c?-1:1));}
struct P{
db x,y;
P(db _x=0,db _y=0){x=_x;y=_y;}
P operator +(const P &b)const{return P(x+b.x,y+b.y);}
P operator -(const P &b)const{return P(x-b.x,y-b.y);}
db operator ^(const P &b)const{return x*b.y-b.x*y;}
db arg()const{return atan2(y,x);}
void ni(){x=-x;y=-y;}
void p(){printf("%lf %lf\n",x,y);}
}a[maxn],b[maxm],c[maxn];
int n,m,N,f[maxm][maxm];
void floyd(){
fo(k,1,m) fo(i,1,m) fo(j,1,m)
if (f[i][k]<2000000000 && f[k][j]<2000000000)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d%d",&n,&m);
fo(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y);
fo(i,1,m) scanf("%lf%lf",&b[i].x,&b[i].y);
memset(f,127,sizeof f);
bool debug=false;
fo(i,1,m){
int mxid=0,mnid=0,lid=0,hid=0;
db low,high;
P mx,mn;
fo(j,1,n){
if (a[j].x==b[i].x && a[j].y==b[i].y) continue;
db x=(a[j]-b[i])^(a[1]-b[i]);
P tmp=(a[j]-b[i]);
if (mxid==0 || equ(mx^tmp,0)>0) mx=tmp,mxid=j;
if (mnid==0 || equ(mn^tmp,0)<0) mn=tmp,mnid=j;
if (hid==0 || high<x) high=x,hid=j;
if (lid==0 || low>x) low=x,lid=j;
}
if (equ((a[hid]-b[i])^(a[lid]-b[i]),0)<0) continue;
P da=mx,xiao=mn;
if (debug) xiao.p(),da.p();
da.ni();
fo(j,1,m)
if (i!=j){
P tmp=b[j]-b[i];
if (debug){
tmp.p();//printf(":%lf %lf\n",xiao^tmp,tmp^da);
printf(":%d %d\n",equ(xiao^tmp,0)<=0,equ(tmp^da,0)<=0);
}
if (equ(xiao^tmp,0)<=0 && equ(tmp^da,0)<=0) f[i][j]=1;
}
if (debug)printf("\n");
}
floyd();
int ans=inf;
fo(i,1,m) ans=min(ans,f[i][i]);
if (ans<2000000000) printf("%d",ans);
else printf("-1");
return 0;
}

最新文章

  1. Hibernate —— 检索策略
  2. [转]iOS开发中@property的属性weak nonatomic strong readonly等介绍
  3. RabbitMQ 发布/订阅
  4. MyBatis Generator自动生成的配置及使用
  5. 解决springmvc中文件下载功能中使用javax.servlet.ServletOutputStream out = response.getOutputStream();后运行出异常但结果正确的问题
  6. [Android教程]EditText设置/隐藏光标位置、选中文本和获取/清除焦点
  7. python练习程序(c100经典例19)
  8. 1245 - Harmonic Number (II)(规律题)
  9. Myeclipse和windows调节成护眼色
  10. foreach循环中为什么不要进行remove/add操作
  11. HTTP Status 500 - Request processing failed; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement
  12. python学习03
  13. Dubbo 源码分析 - 服务导出
  14. sockaddr_in 与 in_addr的区别
  15. RHEL7恢复root密码
  16. Axure 全局变量公式的使用和局部变量
  17. 51nod 贪心算法题集
  18. Python标准库:内置函数type(object)
  19. springMVC定时任务总是执行两次
  20. Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构

热门文章

  1. elasticsearch 过滤器的种类
  2. 如何 在 jQuery 中的 $.each 循环中使用 break 和 continue
  3. shell下时间日期的加减乘除运算
  4. Django项目:CMDB(服务器硬件资产自动采集系统)--10--06CMDB测试Linux系统采集硬件数据的命令05
  5. 63 搜索旋转排序数组II
  6. JEECG-Boot开发环境准备(三):开发环境搭建
  7. 分享一个百度大牛的Python视频系列下载
  8. keras multi-label classification 多标签分类
  9. JasperReports报表组15
  10. Redis学习01——介绍与搭建环境