HYSBZ/BZOJ 1007 [HNOI2008] 水平可见直线 - 计算几何
来源:互联网 发布:windows安装ipython3 编辑:程序博客网 时间:2024/06/14 04:12
题目描述
分析:
直角坐标系内,有n条直线分布,求:最大值(对于任意x,直线上能取到的max( f(x) ))构成的折线由哪些直线构成。
Solution :
把直线按照斜率从小到大排序。
从左到右:先找到中斜率最小的直线 r ,它一定属于ans的集合,找到这条直线与所有直线中横坐标最小的点(x0,y0),由x0确定下一条直线 tar(由于可能出现几条直线交 r 于同一点的情况,取这些直线中斜率最大的。)
根据这样的步骤循环找ans,直到当前直线 r 没有与其他直线的交点了为止。
O(
因为排了序,而且直线的斜率必须由小到大,所以,当当前直线 r 找交点的时候,可以不用考虑斜率小于这条直线的线了,由于当前找到的直线是不确定,所以只有时间上限 O(
代码不好看啊,当时写的时候分了斜率大于0小于0两部分,其实没必要。
推荐一个blogby Liu Junhao
#include<cstdio>#include<algorithm>#include<cmath>using namespace std;#define MAXN 50000#define MAXM 500000#define INF 2147483646const double eps=1e-30;struct node{ int a,b,id;}s[MAXN+10],t[MAXN+10];int n,cnts,cntt,c[MAXM*2+10][2],d[MAXM*2+10][2];bool ans[MAXN+10];bool cmp(node x,node y){ if(x.a==y.a) return x.b>y.b; return x.a<y.a;}void read(){ int x,y; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&x,&y); if(x<0){ if(c[x+MAXM][1]){ if(c[x+MAXM][0]<y) c[x+MAXM][0]=y,c[x+MAXM][1]=i; } else c[x+MAXM][0]=y,c[x+MAXM][1]=i; } else{ if(d[x+MAXM][1]){ if(d[x+MAXM][0]<y) d[x+MAXM][0]=y,d[x+MAXM][1]=i; } else d[x+MAXM][0]=y,d[x+MAXM][1]=i; } } //去掉斜率相同的直线不仅可以优化一小下下,最重要的是避免后面算交点的时候出错(出现除数为0) for(int i=0;i<=MAXM*2;i++){ if(c[i][1]){ s[++cnts].a=i-MAXM,s[cnts].b=c[i][0]; s[cnts].id=c[i][1]; } if(d[i][1]){ t[++cntt].a=i-MAXM,t[cntt].b=d[i][0]; t[cntt].id=d[i][1]; } }}int main(){ read(); sort(s+1,s+cnts+1,cmp); sort(t+1,t+cntt+1,cmp); int r,p,q; bool last; if(cnts){ r=1,p=2,q=1,last=false; ans[s[r].id]=true; } else{ r=1,p=1,q=2,last=true; ans[t[r].id]=true; } double X=-INF; while(true){ int tar=-1; double x0=INF,tmp; bool flag=false; for(int k=p;k<=cnts;k++){ tmp=1.0*(s[k].b-s[r].b)/(s[r].a-s[k].a); if(tmp>=X&&tmp<=x0){ if(fabs(tmp-x0)<=eps){ if(tar!=-1&&s[k].a<s[tar].a) continue; } tar=k; x0=tmp; } } for(int k=q;k<=cntt;k++){ if(last) tmp=1.0*(t[k].b-t[r].b)/(t[r].a-t[k].a); else tmp=1.0*(t[k].b-s[r].b)/(s[r].a-t[k].a); if(tmp>=X&&tmp<=x0){ if(fabs(tmp-x0)<=eps){ if(tar!=-1&&t[k].a<t[tar].a) continue; } tar=k; flag=true; x0=tmp; } } if(tar==-1) break; if(!flag){ if(x0==X) ans[s[r].id]=false; else X=x0; ans[s[tar].id]=true,r=tar; p=tar+1; } else{ if(x0==X){ if(!last) ans[s[r].id]=false; else ans[t[r].id]=false; } else X=x0; ans[t[tar].id]=true,r=tar; p=cnts+1,q=tar+1; } last=flag; } for(int i=1;i<=n;i++) if(ans[i]) printf("%d ",i);}
0 0
- HYSBZ/BZOJ 1007 [HNOI2008] 水平可见直线 - 计算几何
- bzoj 1007: [HNOI2008]水平可见直线(计算几何)
- 【bzoj 1007】[HNOI2008]水平可见直线(计算几何)
- 【计算几何】[HNOI2008][HYSBZ/BZOJ1007]水平可见直线
- BZOJ 1007: [HNOI2008]水平可见直线 几何
- bzoj 1007 [HNOI2008] 水平可见直线 题解
- [BZOJ 1007][HNOI2008]水平可见直线
- [BZOJ 1007] [HNOI2008]水平可见直线
- BZOJ 1007 [HNOI2008]水平可见直线
- BZOJ 1007 [HNOI2008]水平可见直线
- BZOJ 1007: [HNOI2008]水平可见直线
- 【BZOJ 1007】 [HNOI2008]水平可见直线
- [BZOJ 1007][HNOI2008]水平可见直线
- BZOJ 1007 [HNOI2008] 水平可见直线
- BZOJ 1007 [HNOI2008] 水平可见直线
- bzoj 1007 [HNOI2008]水平可见直线
- bzoj 1007: [HNOI2008]水平可见直线
- BZOJ 1007: [HNOI2008]水平可见直线 题解
- 明解C语言1-8
- qq第三方登录常见错误码信息对照表
- 安卓 EditText在用软键盘编辑点击删除键时程序无故闪退
- SpringMvc中ajax后台可以收到请求,前台依旧报错
- 3DS_MAX渲染笔记
- HYSBZ/BZOJ 1007 [HNOI2008] 水平可见直线 - 计算几何
- 网页性能管理详解(原作者: 阮一峰)
- 明解C语言1-9
- Apache和tomcat服务器使用ajp_proxy模块
- Java For Android常用知识总结1
- 加快AppStore审核的两种方式之TestFlight预审核
- gh-pages 首次搭建遇到的坑
- Link-Cut-Tree总结
- 更改XenServer默认安装后根分区大小