hdu 4946 Area of Mushroom(凸包)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4946
Area of Mushroom
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1896 Accepted Submission(s): 452
He has n students guarding the kingdom.
The i-th student stands at the position (xi,yi), and his walking speed is vi.
If a point can be reached by a student, and the time this student walking to this point is strictly less than other students, this point is in the charge of this student.
For every student, Teacher Mai wants to know if the area in the charge of him is infinite.
For each test case, the first line contains one integer n(1<=n<=500).
In following n lines, each line contains three integers xi,yi,vi(0<=|xi|,|yi|,vi<=10^4).
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
直接引用这里了:http://blog.csdn.net/hcbbt/article/details/38582243
题意:
给定n个人,每个人的坐标和移动速度v,若对于某个点,只有 x 能最先到达(即没有人能比x先到这个点或者同时到这个点),则这个点称作被x占有,若有人能占有无穷大的面积 则输出1 ,否则输出0。
分析:
到最后只有速度最大的点才有可能获得无穷大的面积。所以只要考虑速度最大的点。
很明显,只有这些点的凸包边上的点才能获得无穷大的面积。
所以求凸包边上的点就行了。
有几个要注意的坑就是:
1. 如果有点(x,y,v)都相同,那这个点是无法占领无限大的,但是不能不考虑这个点进行凸包,因为这个点会对其他点产生影响。
2. 如果最大速度为0,那么每个点都不会动,所以就不用进行凸包了。
====================================================
多校的题目质量确实高,就这题来说,设了几个坑,最大速度为零的情况,以及三点共线的情况,还有三点在边界上的情况
凸包有两种构建方法,一个是用极角排序,再循环一次
二是直接坐标排序,循环两次
但是第一种情况,对于三点在边界上的情况会少了最后一个点
这也是为什么网上的题解差不多都是第二种方法的原因,第一种方法,如果想用的话,必须先建凸包,
再判断是否在凸包的两点之间那条线上,在的话就保留,当然,会费些时间
----------------------------------------------------------------------------------
第二种方法建凸包:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <algorithm> using namespace std;
#define MAXX 1110
#define eps 1e-8 typedef struct point
{
double x;
double y;
int v;
int id;
} point; bool dy(double x,double y)
{
return x>y+eps;
}
bool xy(double x,double y)
{
return x<y-eps;
}
bool dyd(double x,double y)
{
return x>y-eps;
}
bool xyd(double x,double y)
{
return x<y+eps;
}
bool dd(double x,double y)
{
return fabs(x-y)<eps;
} double crossProduct(point a,point b,point c)
{
return (a.x-c.x)*(b.y-c.y)>(b.x-c.x)*(a.y-c.y);
}
double dist(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
} point p[MAXX];
point stk[MAXX];
int top; bool cmp(point a,point b)
{
if( dd(a.y,b.y))
return xy(a.x,b.x);
return xy(a.y,b.y);
} void Graham(int n)
{
top=;
sort(p,p+n,cmp);
if(n == )
{
top=-;
return ;
}
stk[]=p[];
if(n == )
{
top=;
return;
}
stk[]=p[];
if(n == )
{
top=;
return;
}
stk[]=p[];
for(int i=; i<n; i++)
{
while(top && crossProduct(p[i],stk[top],stk[top-]))
top--;
stk[++top]=p[i];
}
int len=top;
stk[++top]=p[n-];
for(int i=n-; i>=; i--)
{
while(top != len && crossProduct(p[i],stk[top],stk[top-]))
top--;
stk[++top]=p[i];
}
} int main()
{
int i,j,n,m;
int cas=; while(scanf("%d",&n)!=EOF && n)
{
point tmp[MAXX];
int mark[MAXX];
int maxx=;
memset(mark,,sizeof(mark)); for(i=; i<n ; i++)
{ scanf("%lf%lf%d",&tmp[i].x,&tmp[i].y,&tmp[i].v);
if(maxx < tmp[i].v)
{
maxx=tmp[i].v;
}
tmp[i].id=i;
}
if(maxx == )
{ printf("Case #%d: ",cas++);
for(i=; i<n; i++)
printf("%d",mark[i]);
printf("\n");
continue;
}
int id[MAXX];
memset(id,,sizeof(id));
for(i=; i<n; i++)
{ for(j=i+; j<n; j++)
{ if(tmp[i].x == tmp[j].x && tmp[i].y == tmp[j].y && tmp[i].v == tmp[j].v)
{ tmp[i].v=;
id[i]=id[j]=-;
}
}
}
int ss=;
for(i=; i<n; i++)
{ if(maxx == tmp[i].v)
{ p[ss++] = tmp[i];//can??
}
}
Graham(ss);
for(i=; i<=top; i++)
{ if(id[stk[i].id] != -)
{ id[stk[i].id] = ;
}
}
printf("Case #%d: ",cas++);
for(i=; i<n; i++)
printf("%d",id[i]>?:);
printf("\n");
}
return ;
} /*
5
0 0 6
3 3 6
1 1 6
0 3 6
3 0 6
Case #1: 11011
9
0 0 3
0 1 3
0 2 3
1 0 3
1 1 3
1 2 3
2 0 3
2 1 3
2 2 3
Case #2: 111101111
3
0 0 3
1 1 2
2 2 1
Case #3: 100
3
0 0 3
0 0 3
0 0 3
Case #4: 000
8
1 1 3
2 1 3
3 1 3
3 2 3
2 2 3
1 2 3
1 3 3
3 3 3
Case #5: 11110111
4
0 0 3
0 3 3
3 0 3
1 1 3
Case #6: 1110
6
0 0 1
-1 0 1
1 0 1
0 1 1
0 -1 1
0 -1 1
Case #7: 011100
*/
第一种方法建凸包但wa的:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include<iostream>
#include <algorithm> using namespace std;
#define MAXX 1110
#define eps 1e-8 typedef struct point
{ double x;
double y;
int v;
int id;
} point; bool dy(double x,double y)
{
return x>y+eps;
}
bool xy(double x,double y)
{
return x<y-eps;
}
bool dyd(double x,double y)
{
return x>y-eps;
}
bool xyd(double x,double y)
{
return x<y+eps;
}
bool dd(double x,double y)
{
return fabs(x-y)<eps;
} double crossProduct(point a,point b,point c)
{ return (c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x);
}
double dist(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
} point p[MAXX];
point stk[MAXX];
int top; bool cmp(point a,point b)
{ double len=crossProduct(p[],a,b);
if(dd(len,0.0))
{ return xy(dist(p[],a),dist(p[],b));
}
return xy(len ,0.0);
} int Graham(int n)
{ int tmp=;
if(n<) return ;
for(int i=; i<n; i++)
{ if(xy(p[i].x,p[tmp].x) || dd(p[i].x,p[tmp].x) && xy(p[i].y,p[tmp].y))
tmp=i;
}
swap(p[],p[tmp]);
sort(p,p+n,cmp);
top=;
stk[]=p[];
stk[]=p[];
for(int i=; i<n; i++)
{
while(top && xy(crossProduct(stk[top],stk[top-],p[i]),0.0))
top--;
stk[++top]=p[i];//会少一个点
}
/*int len=top;
stk[++top] = p [n-2];
for(int i=n-3; i>=0; i--)
{
while(top != len && xy(crossProduct(stk [top],stk[top-1],p[i]),0.0))
top--;
stk[++top] = p[i];
}*/ return top;
} int main()
{ int i,j,n,m;
int cas=; while(scanf("%d",&n)!=EOF && n)
{
point tmp[MAXX];
int mark[MAXX];
int maxx=;
memset(mark,,sizeof(mark));
for(i=; i<n ; i++)
{ scanf("%lf%lf%d",&tmp[i].x,&tmp[i].y,&tmp[i].v);
if(maxx < tmp[i].v)
{
maxx=tmp[i].v;
}
tmp[i].id=i;
}
if(maxx == )
{
printf("Case #%d: ",cas++);
for(i=; i<n; i++)
printf("%d",mark[i]);
printf("\n");
continue;
}
int id[MAXX];
memset(id,,sizeof(id));
for(i=; i<n; i++)
{ for(j=i+; j<n; j++)
{
if(tmp[i].x == tmp[j].x && tmp[i].y == tmp[j].y &&tmp[i].v == tmp[j].v)
{
tmp[i].v=;
id[i]=id[j]=-;
}
}
}
int ss=;
for(i=; i<n; i++)
{
if(maxx == tmp[i].v)
{
p[ss++]=tmp[i];//can??
}
}
int top=Graham(ss);
for(i=; i<=top; i++)
{
if(id[stk[i].id] != -)
{
id[stk[i].id] = ;
}
}
printf("Case #%d: ",cas++);
for(i=; i<n; i++)
printf("%d",id[i]>?:);
printf("\n");
}
return ;
} /*
5
0 0 6
3 3 6
1 1 6 0 3 6
3 0 6
Case #1: 11011
9
0 0 3
0 1 3
0 2 3
1 0 3
1 1 3
1 2 3
2 0 3
2 1 3
2 2 3
Case #2: 111101111
3
0 0 3
1 1 2
2 2 1
Case #3: 100
3
0 0 3
0 0 3
0 0 3
Case #4: 000
8
1 1 3
2 1 3
3 1 3
3 2 3
2 2 3
1 2 3
1 3 3
3 3 3
Case #5: 11110111
4
0 0 3
0 3 3
3 0 3
1 1 3
Case #6: 1110
6
0 0 1
-1 0 1
1 0 1
0 1 1
0 -1 1
0 -1 1
Case #7: 011100
*/
网上找的第一种方法AC的:(希望原创别喷我)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include <iostream>
#define EPS 1e-8
#define eps 1e-8
using namespace std;
struct TPoint
{
double x,y;
int id,v;
}p[],s[],hull[],pp[];
double cross(TPoint a, TPoint b, TPoint c) {
return (b.x - a.x) * (c.y - a.y) - (c.x - a.x)*(b.y - a.y);
}
double dis(TPoint a,TPoint b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool graham_cmp(const TPoint &b, const TPoint &c) {
double tmp = cross(b, c, p[]);
if (tmp > EPS)
return true;
if (fabs(tmp) < EPS && (dis(b, p[]) < dis(c, p[])))
return true;
return false;
}
int graham_scan(TPoint hull[], int n) {
int top, i, k = ;
for (i = ; i < n; ++i)
if ((p[k].y - p[i].y > EPS)
|| (fabs(p[i].y - p[k].y) < EPS && p[k].x - p[i].x > EPS))
k = i;
swap(p[], p[k]);
sort(p + , p + n, graham_cmp);
hull[] = p[], hull[] = p[], hull[] = p[];
if (n < )
return n;
else
top = ;
for (i = ; i < n; ++i) {
while (top >= && cross(hull[top - ], hull[top - ], p[i]) < EPS)
--top;
hull[top++] = p[i];
}
return top;
}
bool bo[];
int ans[];
bool cmp(TPoint a,TPoint b)
{
return a.x<b.x-eps||(fabs(a.x-b.x)<eps&&a.y<b.y);
}
int main() {
int ri=,n;
while(scanf("%d",&n)&&n)
{
int maxn=;
for(int i=;i<n;++i)
ans[i]=;
for(int i=;i<n;++i)
{
scanf("%lf%lf%d",&s[i].x,&s[i].y,&s[i].v);
s[i].id=i;
maxn=std::max(maxn,s[i].v);
}
if(maxn==)
{
printf("Case #%d: ",++ri);
for(int i=;i<n;++i)
printf("");
puts("");
continue;
}
int tail=;
for(int i=;i<n;++i)
{
if(s[i].v==maxn&&maxn>)
{
pp[tail]=s[i];
p[tail++]=s[i];
}
}
sort(p,p+tail,cmp);
int kk=;
for(int i=;i<tail;++i)
if(i==tail-||fabs(p[i].x-p[i+].x)>eps||fabs(p[i].y-p[i+].y)>eps)
p[kk++]=p[i];
int h=graham_scan(hull,kk);
hull[h]=hull[];
for(int i=;i<tail;++i)
{
int flag=;
for(int j=;j<tail;++j)
if(i!=j&&fabs(pp[i].x-pp[j].x)<eps&&fabs(pp[i].y-pp[j].y)<eps)
{
flag=;
break;
}
if(flag)
{
ans[pp[i].id]=;
continue;
}
bool ok=false;
for(int j=;j<h;++j)
{
if(fabs(cross(pp[i],hull[j],hull[j+]))<eps)
ok=true;
}
if(ok)
ans[pp[i].id]=;
else
ans[pp[i].id]=;
}
printf("Case #%d: ",++ri);
for(int i=;i<n;++i)
printf("%d",ans[i]);
puts(""); }
}
hdu 4946 Area of Mushroom(凸包)的更多相关文章
- HDU 4946 Area of Mushroom 凸包 第八次多校
题目链接:hdu 4946 题意:一大神有N个学生,各个都是小神,大神有个二次元空间,每一个小神都有一个初始坐标,如今大神把这些空间分给徒弟们,规则是假设这个地方有一个人比谁都先到这,那么这个地方就是 ...
- HDU 4946 Area of Mushroom 凸包
链接:pid=4946">http://acm.hdu.edu.cn/showproblem.php?pid=4946 题意:有n个人.在位置(xi,yi),速度是vi,假设对于某个点 ...
- HDU 4946 Area of Mushroom(构造凸包)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4946 题目大意:在一个平面上有n个点p1,p2,p3,p4....pn,每个点可以以v的速度在平面上移 ...
- HDU 4946 Area of Mushroom (几何凸包)
题目链接 题意:给定n个人,每个人有一个速度v方向任意.如果平面中存在一个点只有某个人到达的时间最短(即没有人比这个人到的时间更短或相同),那么我们定义这个店归这个人管辖,现在问这些人中哪些人的管辖范 ...
- HDU 4946 Area of Mushroom 共线凸包
题意是在二维平面上 给定n个人 每一个人的坐标和移动速度v 若对于某个点,仅仅有 x 能最先到达(即没有人能比x先到这个点或者同一时候到这个点) 则这个点称作被x占有 若有人能占有无穷大的面积 则输出 ...
- hdu 4946 Area of Mushroom (凸包,去重点,水平排序,留共线点)
题意: 在二维平面上,给定n个人 每个人的坐标和移动速度v 若对于某个点,只有 x 能最先到达(即没有人能比x先到这个点或者同时到这个点) 则这个点称作被x占有,若有人能占有无穷大的面积 则输出1 , ...
- HDU 4946 Area of Mushroom(2014 Multi-University Training Contest 8)
思路: 只有速度最大才有可能为1,速度不是最大肯定为0,那么就是 只需要操作那些速度最大的点,这些点求一个凸包,判断一下是不是在凸包边上即可. 有几个需要注意的地方: 1.最大速度如果为0 那么肯 ...
- HDU 4946 凸包
给你n个点,具有速度,一个位置如果有其他点能够先到,则不能继续访问,求出里面这些点哪些点是能够无限移动的. 首先我们考虑到,一个速度小的和一个速度大的,速度小的必定只有固定他周围的一定区域是它先到的, ...
- hdu 4946 2014 Multi-University Training Contest 8
Area of Mushroom Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
随机推荐
- 电脑配置 eclipse 环境变量
先找到电脑环境变量 我的电脑——属性——高级系统设置——环境变量 path里面需要两个环境 第一个Java 环境 C:\Program Files\Java\jdk1.8.0_40\bin; 第二个a ...
- C#调用opencv
最经做一个项目,底层调用openCV编写的图像处理程序,用户界面采用C#编写. 于是学习了相关技术,总结如下: C#编写的是托管代码,编译生成微软中间语言,而普通C++代码则编译生成本地机器码,这两种 ...
- python生成数据库中所有表的DESC描述
在数据库设计完成之后, 常常需要在 wiki 或其他文档中保存一份数据库中所有表的 desc 描述, 尤其是每个字段的含义和用途. 手动去生成自然是不可取的. 因此, 我编写了一个简单的 python ...
- BlueDroid介绍 【转】
转自:http://blog.csdn.net/fen_liu/article/details/41213167 [-] 基本结构 代码区 http://www.cnblogs.com/hzl6255 ...
- node-webkit 新建实例窗口间通信问题解决办法
终于弄明白这问题了,只要在js文件里加上段代码,就可解决两窗口间通信问题. var str = { username: User.name, userrole: User.role }; var ne ...
- [HTML]表格的一切
如何设置HTML页面自适应宽度的table(表格): <table width="95%" border="1" cellpadding="2& ...
- Android 内存优化 (防Memory Leak)
在之前的 Android 内存管理 &Memory Leak & OOM 分析 中,说到了Android的内存管理相关的原理,也能了解到Android Memory Leak 和 ...
- 用R分析时间序列(time series)数据
时间序列(time series)是一系列有序的数据.通常是等时间间隔的采样数据.如果不是等间隔,则一般会标注每个数据点的时间刻度. time series data mining 主要包括decom ...
- spring Aop中aop:advisor 与 aop:aspect的区别
转载:http://blog.csdn.net/u011710466/article/details/52888277 在spring的配置中,会用到这两个标签.那么他们的区别是什么呢? ...
- linux 帮助命令
帮助命令 man(manual) 可以用来查看1 命令 2 配置文件 格式 man ls 1 查看命令 看第一行NAME 如果要看-l ,那么直接输入/-l 2 查看配置文件 man 查看配置文件信息 ...