题目大意:

  一些点在一张无穷图上面,每个点可以控制一些区域,这个区域满足这个点到达这个区域的时间严格小于其他点。求哪些点能够控制无穷面积的区域。

题目思路:

  速度小的控制范围一定有限。

  速度最大当且仅当在凸包上才能够控制无穷区域。可以通过,任意两个点中垂线为界,左右各控制一半,判断出凸包内的点仅能控制有限区域。

   

  特判:

    速度最大且在同一个点上的点均不能控制无穷区域,但是要加入凸包计算。

    速度最大为0不能控制无穷区域。

对于共线凸包(Graham),(代码中有解释)

  均不能存在重点!可用map判重。

   1、按极角坐标序排

      缺点:需要将最后一条边上的点逆序排,才能够将最后一边共线点加入凸包。

   2、按水平序排。

      缺点:若所有点在一条直线上,会产生将所有点入凸包1~n~2的情况,需要特判,当然本题只是用到这些点,无需判断是否重复出现。

极角序:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <map>
#include <deque>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define INF 0x3f3f3f3f using namespace std; const int MAXN = ;
const double eps = 1e-;
const double PI = acos(-1.0); int tx,ty,tv,maxv,n,N,cas;
bool pd[MAXN]; int sgn(double x)
{
if(fabs(x) < eps) return ;
if(x < ) return -;
return ;
}
struct Point
{
double x,y;
int re;
Point(){}
Point(double _x, double _y): x(_x),y(_y) {}
Point operator -(const Point &B) const
{
return Point(x-B.x, y-B.y);
}
Point operator +(const Point &B) const //向量相加
{
return Point(x+B.x, y+B.y);
}
double operator ^(const Point &B) const //叉积
{
return x*B.y - y*B.x;
}
double operator *(const Point &B) const //点积
{
return x*B.x + y*B.y;
}
bool operator ==(const Point &B) const
{
return fabs(B.x-x)<eps && fabs(B.y-y)<eps;
}
bool operator !=(const Point &B) const
{
return !((*this) == B);
}
double norm()//向量的模
{
return sqrt(x*x+y*y);
}
void transXY(double B) //绕原点逆时针旋转B弧度
{
double tx = x, ty = y;
x = tx*cos(B) - ty*sin(B);
y = tx*sin(B) + ty*cos(B);
}
void input() //读入只能用double读入
{
scanf("%lf%lf",&x,&y);
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point _s, Point _e)
{
s=_s; e=_e;
}
}; double dist(Point a, Point b)
{
return sqrt((a-b)*(a-b));
} //判断点在线段上
bool OnS(Point A, Line a)
{
return
sgn((a.s-A)^(a.e-A)) == &&
sgn((A.x-a.s.x)*(A.x-a.e.x)) <= &&
sgn((A.y-a.s.y)*(A.y-a.e.y)) <= ;
} //求凸包 Graham算法
//点的编号0~n-1
//返回凸包结果Stack[0~top-1]为凸包的编号
//一个点或两个点 则凸包为一或二个点
int Stack[MAXN],top;
Point vertex[MAXN];
bool Graham_cmp(Point A, Point B)
{
double tmp=(A-vertex[])^(B-vertex[]);
if(sgn(tmp) > ) return ;
if(sgn(tmp) == && sgn(dist(A,vertex[])-dist(B,vertex[])) <= ) return ;
return ;
}
void Graham(int n)
{
int k=;
for(int i=; i<n; i++)
if((vertex[k].y>vertex[i].y) || (vertex[k].y==vertex[i].y && vertex[k].x>vertex[i].x))
k=i;
swap(vertex[], vertex[k]);
sort(vertex+, vertex+n, Graham_cmp);
if(n == )
{
top=;
Stack[]=;
return;
}
if(n == )
{
top=;
Stack[]=;
Stack[]=;
return;
} int tmp;
for(tmp=n-; tmp> && sgn((vertex[]-vertex[tmp])^(vertex[]-vertex[tmp-])) == ; tmp--);
reverse(vertex+tmp,vertex+n);//最后一条边倒序 Stack[]=;
Stack[]=;
top=;
for(int i=; i<n; i++)
{
while(top > && (vertex[i] == vertex[Stack[top-]] || sgn((vertex[Stack[top-]]-vertex[Stack[top-]])^(vertex[i]-vertex[Stack[top-]])) < ))//相同点只进栈一次 同一条线上的点也进栈
top--;
Stack[top++]=i;
}
} int main()
{
// freopen("1002.in","r",stdin);
// freopen("1002p.out","w",stdout);
while(scanf("%d",&N)!=EOF && N)
{
memset(pd,,sizeof(pd));
n=;
maxv=-;
for(int i=; i<N; i++)
{
scanf("%d%d%d",&tx,&ty,&tv);
if(maxv==tv)
{
vertex[n].x=tx;
vertex[n].y=ty;
vertex[n].re=i;
n++;
}
else
if(maxv<tv)
{
maxv=tv;
n=;
vertex[n].x=tx;
vertex[n].y=ty;
vertex[n].re=i;
n++;
}
}
Graham(n); for(int i=; i<top; i++)
pd[vertex[Stack[i]].re]=; for(int i=; i<n; i++)//去掉相同点
for(int j=i+; j<n; j++)
if(vertex[i]==vertex[j])
{
pd[vertex[i].re]=;
pd[vertex[j].re]=;
} printf("Case #%d: ",++cas);
for(int i=; i<N; i++)
{
if(maxv==) printf("");
else printf("%d",pd[i]);
}
printf("\n");
}
return ;
} /*
0 0 1
0 1
0 1
1 1
2 1
3 1
1 1 */

水平序:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <map>
#include <deque>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define INF 0x3f3f3f3f using namespace std; const int MAXN = ;
const double eps = 1e-;
const double PI = acos(-1.0); int tx,ty,tv,maxv,n,N,cas;
int pd[MAXN]; int sgn(double x)
{
if(fabs(x) < eps) return ;
if(x < ) return -;
return ;
}
struct Point
{
double x,y;
int re;
Point(){}
Point(double _x, double _y): x(_x),y(_y) {}
Point operator -(const Point &B) const
{
return Point(x-B.x, y-B.y);
}
Point operator +(const Point &B) const //向量相加
{
return Point(x+B.x, y+B.y);
}
double operator ^(const Point &B) const //叉积
{
return x*B.y - y*B.x;
}
double operator *(const Point &B) const //点积
{
return x*B.x + y*B.y;
}
bool operator ==(const Point &B) const
{
return fabs(B.x-x)<eps && fabs(B.y-y)<eps;
}
bool operator !=(const Point &B) const
{
return !((*this) == B);
}
double norm()//向量的模
{
return sqrt(x*x+y*y);
}
void transXY(double B) //绕原点逆时针旋转B弧度
{
double tx = x, ty = y;
x = tx*cos(B) - ty*sin(B);
y = tx*sin(B) + ty*cos(B);
}
bool operator<(const Point B) const
{
return(x<B.x || (x==B.x && y<B.y));
}
void input() //读入只能用double读入
{
scanf("%lf%lf",&x,&y);
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point _s, Point _e)
{
s=_s; e=_e;
}
}; double dist(Point a, Point b)
{
return sqrt((a-b)*(a-b));
} //判断点在线段上
bool OnS(Point A, Line a)
{
return
sgn((a.s-A)^(a.e-A)) == &&
sgn((A.x-a.s.x)*(A.x-a.e.x)) <= &&
sgn((A.y-a.s.y)*(A.y-a.e.y)) <= ;
} //求凸包 Graham算法
//点的编号0~n-1
//返回凸包结果Stack[0~top-1]为凸包的编号
//一个点或两个点 则凸包为一或二个点
int Stack[MAXN],top;
Point vertex[MAXN];
bool Graham_cmp(Point A, Point B)
{
return A.y<B.y || (A.y == B.y && A.x<B.x);
}
void Graham(int n)
{
sort(vertex, vertex+n, Graham_cmp);
top=;
for(int i=; i<n; i++)
{
while(top > && sgn((vertex[Stack[top-]]-vertex[Stack[top-]])^(vertex[i]-vertex[Stack[top-]])) < )//改为<即可
top--;
Stack[top++]=i;
}
int tmp=top;
for(int i=n-; i>=; i--)
{
while(top > tmp && sgn((vertex[Stack[top-]]-vertex[Stack[top-]])^(vertex[i]-vertex[Stack[top-]])) < )
top--;
Stack[top++]=i;
}
if(n>) top--;
} int main()
{
freopen("1002.in","r",stdin);
freopen("1002p.out","w",stdout);
map<Point,int> mapp;
while(scanf("%d",&N)!=EOF && N)
{
memset(pd,-,sizeof(pd));
n=;
maxv=-;
for(int i=; i<=N; i++)
{
scanf("%d%d%d",&tx,&ty,&tv);
if(maxv==tv && mapp[Point(tx,ty)]>)
{
pd[mapp[Point(tx,ty)]]=;
pd[i]=;
continue;
}
if(maxv==tv)
{
vertex[n].x=tx;
vertex[n].y=ty;
vertex[n].re=i;
mapp[vertex[n]]=i;
n++;
}
if(maxv<tv)
{
mapp.clear();
maxv=tv;
n=;
vertex[n].x=tx;
vertex[n].y=ty;
vertex[n].re=i;
mapp[vertex[n]]=i;
n++;
}
} Graham(n); for(int i=; i<top; i++)
if(pd[vertex[Stack[i]].re]==-)
pd[vertex[Stack[i]].re]=; printf("Case #%d: ",++cas);
for(int i=; i<=N; i++)
if(maxv==) printf("");
else
{
if(pd[i]<=) printf("");
else printf("");
}
printf("\n");
}
return ;
} /*
0 0 1
0 1
0 0
0 1
0 1
0 0 1
0 1
0 1
1 1
2 1
3 1
1 1 */

水平序优化:(可以解决重点+共线凸包问题)

  vis判水平序的点是否访问过,防止一条线的情况。

  pd判是否重点,在水平排序后相邻的一定相邻!写的还算漂亮。毕竟map太暴力了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <utility>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define MAXN 505
#define eps 1e-4 using namespace std; struct Point{
double x,y;
int res;
Point(){}
Point(double _x, double _y): x(_x),y(_y){}
double operator^(Point A)
{
return x*A.y-A.x*y;
}
Point operator -(const Point A) const
{
return Point(x-A.x,y-A.y);
}
}vertex[MAXN]; int Stack[MAXN],top;
int N,n,x,y,v,Case;
bool vis[MAXN],pd[MAXN]; inline double dist(Point A)
{
return sqrt(A.x*A.x+A.y*A.y);
} int sgn(double x)
{
if(fabs(x)<eps) return ;
if(x<) return -;
return ;
} bool cmp(Point A, Point B)
{
return A.y<B.y || (A.y==B.y && A.x<B.x);
} void Graham(int n)
{
sort(vertex,vertex+n,cmp);
for(int i=; i<n-; i++)
if(sgn(dist(vertex[i]-vertex[i+]))==)
pd[vertex[i].res]=pd[vertex[i+].res]=;
top=;
for(int i=; i<n; i++)
{
while(top> && (sgn(dist(vertex[Stack[top-]]-vertex[Stack[top-]]))== || sgn((vertex[Stack[top-]]-vertex[Stack[top-]])^(vertex[i]-vertex[Stack[top-]]))<))
vis[Stack[--top]]=;
Stack[top++]=i;
vis[i]=;
}
int tmp=top;
for(int i=n-; i>=; i--)
{
while(top>tmp && (sgn(dist(vertex[Stack[top-]]-vertex[Stack[top-]]))== || sgn((vertex[Stack[top-]]-vertex[Stack[top-]])^(vertex[i]-vertex[Stack[top-]]))<))
vis[Stack[--top]]=;
if(!vis[i]) Stack[top++]=i;
}
//if(n>1) top--;
} int main()
{
while(scanf("%d",&N)!=EOF && N)
{
int maxv=-;
for(int i=; i<N; i++)
{
scanf("%d%d%d",&x,&y,&v);
if(v<maxv) continue;
if(v>maxv)
{
maxv=v;
n=;
}
vertex[n].x=x;
vertex[n].y=y;
vertex[n].res=i;
n++;
}
memset(vis,,sizeof(vis));
memset(pd,,sizeof(pd));
Graham(n);
// for(int i=0; i<top; i++)
// printf("%f %f\n",vertex[Stack[i]].x,vertex[Stack[i]].y);
printf("Case #%d: ",++Case);
memset(vis,,sizeof(vis));
if(maxv>)
{
for(int i=; i<top; i++)
vis[vertex[Stack[i]].res]=;
}
for(int i=; i<N; i++)
printf("%d",vis[i]&&pd[i]);
printf("\n");
}
return ;
}

HDU 4946 共线凸包的更多相关文章

  1. HDU 4946 Area of Mushroom 凸包 第八次多校

    题目链接:hdu 4946 题意:一大神有N个学生,各个都是小神,大神有个二次元空间,每一个小神都有一个初始坐标,如今大神把这些空间分给徒弟们,规则是假设这个地方有一个人比谁都先到这,那么这个地方就是 ...

  2. HDU 4946 凸包

    给你n个点,具有速度,一个位置如果有其他点能够先到,则不能继续访问,求出里面这些点哪些点是能够无限移动的. 首先我们考虑到,一个速度小的和一个速度大的,速度小的必定只有固定他周围的一定区域是它先到的, ...

  3. HDU 5928 DP 凸包graham

    给出点集,和不大于L长的绳子,问能包裹住的最多点数. 考虑每个点都作为左下角的起点跑一遍极角序求凸包,求的过程中用DP记录当前以j为当前末端为结束的的最小长度,其中一维作为背包的是凸包内侧点的数量.也 ...

  4. HDU 4946 Area of Mushroom 共线凸包

    题意是在二维平面上 给定n个人 每一个人的坐标和移动速度v 若对于某个点,仅仅有 x 能最先到达(即没有人能比x先到这个点或者同一时候到这个点) 则这个点称作被x占有 若有人能占有无穷大的面积 则输出 ...

  5. hdu 4946 Area of Mushroom(凸包)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4946 Area of Mushroom Time Limit: 2000/1000 MS (Java/Ot ...

  6. HDU 4946 Area of Mushroom(构造凸包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4946 题目大意:在一个平面上有n个点p1,p2,p3,p4....pn,每个点可以以v的速度在平面上移 ...

  7. HDU 4946 Area of Mushroom 凸包

    链接:pid=4946">http://acm.hdu.edu.cn/showproblem.php?pid=4946 题意:有n个人.在位置(xi,yi),速度是vi,假设对于某个点 ...

  8. hdu 4946 凸包注意重点

    http://acm.hdu.edu.cn/showproblem.php?pid=4946 给你n个点的坐标和速度,如果一个点能够到达无穷远处,且花费的时间是最少的,则此点输出1,否则输出0. 每个 ...

  9. hdu 4946 Area of Mushroom (凸包,去重点,水平排序,留共线点)

    题意: 在二维平面上,给定n个人 每个人的坐标和移动速度v 若对于某个点,只有 x 能最先到达(即没有人能比x先到这个点或者同时到这个点) 则这个点称作被x占有,若有人能占有无穷大的面积 则输出1 , ...

随机推荐

  1. SQL SERVER 强制排序规则查询

    有时会需要在2个DB之间的数据做比较, 但因为一些原因, 数据库的默认排序规则是不一样的, 例如 SELECT A.Col1, B.Col1, A.* FROM DB1.dbo.A LEFT JOIN ...

  2. busying

    罪过 ,最近好忙  ,好久没有发表东西了, 连英语单词都写错了

  3. MYSQL远程登录权限设置

    Mysql默认关闭远程登录权限,如下操作允许用户在任意地点登录: 1. 进入mysql,GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY ...

  4. android开发设置dialog的高宽

    这里设置为跟屏幕一样的宽度,:看代码 dlg.show(); WindowManager.LayoutParams params = dlg.getWindow().getAttributes(); ...

  5. android 开发解密时出现pad block corrupted 错误

    情景:在虚拟机上运行正常的,但是到我的真机上就解密失败,出现pad block corrupted  ,据说是版本原因:我机器是小米3 最新版的android  4.2 出现问题的代码: privat ...

  6. javacript中的mvc设计模式

    以下内容为原创翻译,翻译不对的地方还请原谅,凑合着看吧. 原文网址是: 来源:http://www.alexatnet.com/articles/model-view-controller-mvc-j ...

  7. Django 学习笔记之四 QuerySet常用方法

    QuerySet是一个可遍历结构,它本质上是一个给定的模型的对象列表,是有序的. 1.建立模型: 2.数据文件(test.txt) 3.文件数据入库(默认的sqlite3) 入库之前执行 数据库同步命 ...

  8. linux进程管理之服务

     init进程首先通过initable查看运行级别,然后运行rc.d下面的sysinit,然后调用rc,然后运行rc###连接到init.d下面的服务.自启动. chkconfig命令只是查看和设置服 ...

  9. Unity3D脚本中文系列教程(十)

    http://dong2008hong.blog.163.com/blog/static/4696882720140312627682/?suggestedreading&wumii Unit ...

  10. JAVA WEB中如何让数据库连接对开发人员完全透明?

    书上的技术,确实开了眼界. 列相关测试代码如下,慢慢体会开发的模式. PropsUtil package org.smart4j.chapter2.util; import java.io.FileN ...