POJ-1696 Space Ant 凸包版花式水过!
2017-01-08 20:12
232 查看
Space Ant
明天早上最后一科毛概了,竟然毫无复习之意,沉迷刷题无法自拔~~
题意:说实话没有仔细看,大概是一只右眼失明(只能左转)的蚂蚁每天要吃掉一个点的食物才能活下去,现在给出n个点的坐标,求蚂蚁最多能活多少天?
一看就是循环求凸包一直往里循环,数据只有50,这让我有勇气尝试一发。样例水过了却WA了三发。讨论区说的是用点积或者叉积,但我觉得循环凸包思路也行啊。吃饭的时候突然意识到我每次都是用未访问过的点找最坐下端的点排序,却疏漏了如果求最外层的凸包当然可以这样,但此题要循环求内层的凸包,所以外层用完标记然后把最后一个点作为起始点参考排序,回来改改A了。当然我知道是后台较水。。struct node
{
int x,y,i;
} a
,p
;
int n,tot,len,ans[60],v[60];
double dis(node a,node b)
{
return hypot(a.x-b.x,a.y-b.y);
}
int multi(node p0,node p1,node p2)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
int cmp(node p1,node p2)
{
int x=multi(p1,p2,a[0]);
if(x>0||(x==0&&dis(p1,a[0])<dis(p2,a[0]))) return 1;
return 0;
}
void Graham()
{
sort(a+1,a+n,cmp);//a[0]是上一轮最后一个点即本轮的出发点,以其作为参考来极角排序
tot=2,p[0]=a[0],p[1]=a[1];
for(int i=2; i<n; i++)
{
while(tot>1&&multi(a[i],p[tot-1],p[tot-2])>=0) tot--;
p[tot++]=a[i];
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(v,0,sizeof(v));
scanf("%d",&n);
for(int i=0; i<n; i++) scanf("%d%d%d",&a[i].i,&a[i].x,&a[i].y);
len=0;
int k=0;
for(int i=1; i<n; i++)
if((a[i].y<a[k].y||(a[i].y==a[k].y&&a[i].x<a[k].x))) k=i;//找到最左下角的;
swap(a[0],a[k]);
ans[len++]=a[0].i;
v[a[0].i]=1;
while(n>1)
{
Graham();//获取凸包上的点;
for(int i=1; i<tot; i++)//a[0]每次
{
ans[len++]=p[i].i;
v[p[i].i]=1;//已访问过
}
a[0]=p[tot-1];
int nn=0;
for(int i=0; i<n; i++) if(!v[a[i].i]) p[nn++]=a[i];//凸包内的点;
for(int i=0; i<nn; i++) a[i+1]=p[i];
n=nn+1;//加上a[0]共nn+1个点;
}
printf("%d",len);
for(int i=0; i<len; i++)
printf(" %d",ans[i]);
printf("\n");
}
return 0;
}
明天早上最后一科毛概了,竟然毫无复习之意,沉迷刷题无法自拔~~
题意:说实话没有仔细看,大概是一只右眼失明(只能左转)的蚂蚁每天要吃掉一个点的食物才能活下去,现在给出n个点的坐标,求蚂蚁最多能活多少天?
一看就是循环求凸包一直往里循环,数据只有50,这让我有勇气尝试一发。样例水过了却WA了三发。讨论区说的是用点积或者叉积,但我觉得循环凸包思路也行啊。吃饭的时候突然意识到我每次都是用未访问过的点找最坐下端的点排序,却疏漏了如果求最外层的凸包当然可以这样,但此题要循环求内层的凸包,所以外层用完标记然后把最后一个点作为起始点参考排序,回来改改A了。当然我知道是后台较水。。struct node
{
int x,y,i;
} a
,p
;
int n,tot,len,ans[60],v[60];
double dis(node a,node b)
{
return hypot(a.x-b.x,a.y-b.y);
}
int multi(node p0,node p1,node p2)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
int cmp(node p1,node p2)
{
int x=multi(p1,p2,a[0]);
if(x>0||(x==0&&dis(p1,a[0])<dis(p2,a[0]))) return 1;
return 0;
}
void Graham()
{
sort(a+1,a+n,cmp);//a[0]是上一轮最后一个点即本轮的出发点,以其作为参考来极角排序
tot=2,p[0]=a[0],p[1]=a[1];
for(int i=2; i<n; i++)
{
while(tot>1&&multi(a[i],p[tot-1],p[tot-2])>=0) tot--;
p[tot++]=a[i];
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(v,0,sizeof(v));
scanf("%d",&n);
for(int i=0; i<n; i++) scanf("%d%d%d",&a[i].i,&a[i].x,&a[i].y);
len=0;
int k=0;
for(int i=1; i<n; i++)
if((a[i].y<a[k].y||(a[i].y==a[k].y&&a[i].x<a[k].x))) k=i;//找到最左下角的;
swap(a[0],a[k]);
ans[len++]=a[0].i;
v[a[0].i]=1;
while(n>1)
{
Graham();//获取凸包上的点;
for(int i=1; i<tot; i++)//a[0]每次
{
ans[len++]=p[i].i;
v[p[i].i]=1;//已访问过
}
a[0]=p[tot-1];
int nn=0;
for(int i=0; i<n; i++) if(!v[a[i].i]) p[nn++]=a[i];//凸包内的点;
for(int i=0; i<nn; i++) a[i+1]=p[i];
n=nn+1;//加上a[0]共nn+1个点;
}
printf("%d",len);
for(int i=0; i<len; i++)
printf(" %d",ans[i]);
printf("\n");
}
return 0;
}
相关文章推荐
- react native 抽屉效果
- Eclipse 集成环境运行HelloWorld
- 后台管理工程搭建
- jquery 无限极联动【地区】
- 2016年科技行业中最大的失言和吹嘘
- js模板引擎实现原理
- Linux作业(3)
- 80老翁谈人生(330):为什么《网络安全法》的准确含义是《网络空间法》?
- C#视频之值类型和引用类型
- Cocos2d-x 3.x 图形学渲染系列九
- CodeForces - 269C Flawed Flow
- Cocos2d-x 3.x 图形学渲染系列九
- 七牛云ajax上传图片(MultipartFile 转file)
- in
- mongdb 入门二
- 笔记本安装ubuntu出现wifi已通过硬件开关禁用解决方法
- 《软件设计重构》读书笔记(6)-层次结构型缺陷
- UVA 1349 Optimal Bus Route Design(KM判环)
- nginx配置https并强制http自动跳转到https
- 2017第一周日