zoukankan      html  css  js  c++  java
  • 【BZOJ】1007 水平可见直线

    【分析】
    维护一个下凸包。
    首先依照斜率来从小到大排序。


    考虑斜率同样的,肯定仅仅能选截距大的,把截距小的给筛掉。


    然后用栈来维护下凸包。先压入前两条直线。
    然后对于每一条直线i,设栈中上一条直线p=stk[stk[0]]和上上条直线q=stk[stk[0]-1]。
    找到i与p的交点m。p与q的交点n。
    画三条直线,把n点看成固定的,因为斜率从小到大,要使得上一条直线p看不到。那么m一定在n的左边,即m.x<=n.x。


    假设看不到,就退栈,直到在右边。


    最后输出,注意可能会存在n=1的情况。这个么,随便处理罢...

    PS:网上的代码大多数都是错的,结果还能AC,这道题的数据非常水哟。

    【代码】

    <span style="font-size:18px;">#include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    const int N=50000;
    const double eps=1e-5;
    
    struct Line
    {
    	double k,b;
    	int id;
    }line[N],_line[N];
    struct Point
    {
    	double x,y;
    }now,last;
    int n,_n,stk[N];
    
    inline int dc(double i,double j)
    {
    	if (fabs(i-j)<eps) return 0;
    	return i<j?-1:1;
    }
    
    int cmp(Line La,Line Lb)
    {
    	int r=dc(La.k,Lb.k);
    	return r?r<0:dc(La.b,Lb.b)>0;
    }
    
    inline Point get_point(int i,int j)
    {
    	double k1=_line[i].k,b1=_line[i].b,k2=_line[j].k,b2=_line[j].b; Point P;
    	P.x=(b2-b1)/(k1-k2);
    	P.y=(b1*k2-b2*k1)/(k1-k2);
    	return P;
    }
    
    inline int cmp1(int i,int j)
    {
    	return _line[i].id<_line[j].id;
    }
    
    int main(void)
    {	
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    		scanf("%lf%lf",&line[i].k,&line[i].b),line[i].id=i;
    	
    	sort(line+1,line+n+1,cmp);
    	for (int i=1;i<=n;i++)
    	{
    		if (_n&&!dc(line[i].k,_line[_n].k)) continue;
    		_line[++_n]=line[i];
    	}
    	
    	stk[++stk[0]]=1,stk[++stk[0]]=2;
    	for (int i=3;i<=_n;i++)
    	{
    		if (stk[0]&&!dc(_line[stk[stk[0]]].k,_line[i].k)) continue;
    		for (;stk[0]>=2;)
    		{
    			last=get_point(stk[stk[0]-1],stk[stk[0]]);
    			now=get_point(stk[stk[0]],i);
    			if (last.x>=now.x) stk[stk[0]--]=0; else break;
    		}
    		stk[++stk[0]]=i;
    	}
    
    	sort(stk+1,stk+stk[0]+1,cmp1);
    	for (int i=1;i<=stk[0];i++)
    	{
    		if (!line[i].id) continue;
    		printf("%d ",_line[stk[i]].id);
    	}
    	printf("
    ");
    	
    	return 0;
    }</span>


  • 相关阅读:
    Linux查看系统信息
    pgrep 和 pkill 使用小记
    linux下json库的编译及例程
    Epoll 实例
    gcc中的内嵌汇编语言
    BZOJ 1053: [HAOI2007]反素数ant
    2018.7.15模拟赛
    BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊
    BZOJ 4241: 历史研究
    LUOGU P2365 任务安排
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/6884230.html
Copyright © 2011-2022 走看看