题面

养鸽人要监视他的鸽子,有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;
}

【JZOJ5094】【GDSOI2017第四轮模拟day3】鸽子 计算几何+floyd的更多相关文章

  1. 【JZOJ5093】【GDSOI2017第四轮模拟day3】字符串匹配 哈希

    题面 对于一个字符集大小为C的字符串P,我们可以将任意两种字符在P中的位置进行互换,例如P=abcba,我们交换a,b就变为bacab,交换a,d就变为dbcbd,交换可以进行任意次.若交换后P变为了 ...

  2. [第一波模拟\day3\T3]{益智游戏}(game.cpp)

    [问题描述] 小P和小R在玩一款益智游戏.游戏在一个正权有向图上进行. 小P控制的角色要从A点走最短路到B点,小R控制的角色要从C点走最短路到D点. 一个玩家每回合可以有两种选择,移动到一个相邻节点或 ...

  3. [第一波模拟\day3\T2]{独立集}(bubble.cpp)

    [问题描述] 有一天,一个名叫顺旺基的程序员从石头里诞生了.又有一天,他学会了冒泡排序和独立集.在一个图里,独立集就是一个点集,满足任意两个点之间没有边.于是他就想把这两个东西结合在一起.众所周知,独 ...

  4. HNOI模拟 Day3.25 By Yqc

    怕老婆 [问题描述] 有一天hzy9819,来到了一座大城市拥有了属于他自己的一双滑板鞋.但是他还是不满足想要拥有属于自己的一栋楼,他来到了一条宽敞的大道上,一个一个记录着这些楼的层数以方便自己选择. ...

  5. HNOI模拟 Day3.23

    一.拓扑(top)[ 题目描述]:给你一个有向二分图,求他的拓扑序列的个数.[ 输入]:第一行两个数 N,M,表示点数和边数.接下来 M 行每行两个数 a,b,表示 a 向 b 有一条有向边.[ 输出 ...

  6. HNOI模拟 Day3.22

    第一题: 盾盾的打字机 (drdrd) [题目描述] 盾盾有一个非常有意思的打字机,现在盾哥要用这台打字机来打出一段文章. 由于有了上次的经验,盾盾预先准备好了一段模板 A 存在了内存中,并以此为基础 ...

  7. 【JZOJ5088】【GDOI2017第四轮模拟day2】最小边权和 排序+动态规划

    题面 有一张n个点m条边的有向图,每条边有一个互不相同的边权w,有q个询问,要求你从点a经过不超过c条边到点b,要求经过的边权递增并和尽量小,求出最小的边权和,如果没有合法方案则输出-1. 对于100 ...

  8. 【JZOJ5086】【GDOI2017第四轮模拟day1】数列 折半搜索

    题面 有一个长度为n 的排列,现在有一些位置的数已经模糊不清了,你只知道这个排列的逆序对个数是K,你能计算出总共有多少可能的排列吗? 对于100% 的数据,n <=10^3,K<=10^9 ...

  9. 【JZOJ5081】【GDSOI2017第三轮模拟】Travel Plan 背包问题+双指针+树的dfs序

    题面 100 注意到ban的只会是一个子树,所以我们把原树转化为dfs序列. 然后题目就转化为,询问一段ban的区间,之后的背包问题. 比赛的时候,我想到这里,于是就开始想区间合并,于是搞了线段树合并 ...

随机推荐

  1. 02_jQuery对象初识(二)筛选器1

    0. HTML对象和jQuery对象的区别: 1.jQuery对象转换成DOM对象,用索引取出具体的标签 2.DOM对象转换成jQuery对象,$(DOM对象) 注意:jQuery对象保存到变量的时候 ...

  2. Activiti 部分实用功能

    helloworld中已经写了关于部署流程图,查询个人任务,完成个人任务部分.现在添加几个新的实用功能 1.判断流程是否完成,代码如下 public void isProcessEnd() { Str ...

  3. linux NC网络通信工具的安装

    由于开发socket一类工具需要用到管道进行测试,就想到安装个linux nc工具来测试 于是上网找了个rpm安装完发现不可用(公司服务器没外网) 报错内容: [root@rhel071 instal ...

  4. InceptionV3代码解析

    InceptionV3代码解析 参考博文:https://blog.csdn.net/superman_xxx/article/details/65451916 读了Google的GoogleNet以 ...

  5. python基础-迭代器

    1.迭代:指的是一个重复的过程,每一次重复称为一次迭代,并且每一次重复的结果 是下一次重复的初始值 2.为什么要有迭代器 对于序列类型:str list tuple 可以依赖索引来迭代取值,但是对于d ...

  6. 关于判断是安卓还是ios环境跳转下载页

    H5项目中判断是安卓还是iOS手机就跳转到不同的下载页,项目如下https://github.com/JserJser/dailyPush/tree/master/daily6/H5 这个项目里面我比 ...

  7. c语言一个例子对比php学习随记

    今天开始学写一些简单的C例子,发现很多和PHP不一样的地方,做个笔记. #include <stdio.h> int main(void) { int a,b; printf(" ...

  8. 取消 ios 上下滑动

  9. CentOS 7 忘记root密码的修改方法

    1.开机按esc 2.选择CentOS Linux (3.10.0-693.......)     按 e 键: 3.光标移动到 linux 16 开头的行,找到 ro 改为 rw init=sysr ...

  10. Leetcode455.Assign Cookies分发饼干

    假设你是一位很棒的家长,想要给你的孩子们一些小饼干.但是,每个孩子最多只能给一块饼干.对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸:并且每块饼干 j ,都有一个尺寸 ...