• BZOJ1007水平可見直線 計算幾何


    @[計算幾何]

    Description

    在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为
    可见的,否则Li为被覆盖的.
    例如,对于直线:
    L1:y=x; L2:y=-x; L3:y=0
    则L1和L2是可见的,L3是被覆盖的.
    给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.

    Input

    第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi

    Output

    从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格

    Sample Input

    3
    -1 0
    1 0
    0 0
    

    Sample Output

    1 2
    

    Solution

    算法比较直观,先按斜率排序,再将最小的两条线入栈,然后依次处理每条线,如果其与栈顶元素的交点在上一个点的左边,则将栈顶元素出栈 ;这样为什么对呢?因为对如任意一个开口向上的半凸包,从左到右依次观察每条边和每个顶点,发现假如其能被觀察到, 則其斜率不断增大,顶点的横坐标也不断增大。

    很簡單的思路就是: 先想到按斜率(節距)排一下序, 然後在紙上畫一下, 大概就知道是怎麼回事了. 注意在斜率相同節距不同時的處理不要出錯.

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    const int N = 1 << 16;
    const float EPS = 1e-8;
    struct Line
    {
    	float a, b;
    	int ID;
    }line[N];
    int operator <(Line x, Line y)
    {
    	if(fabs(x.a - y.a) < EPS)
    		return x.b < y.b;
    	return x.a < y.a;
    }
    int top;
    Line stack[N];
    float get(Line x, Line y)
    {
    	return (y.b - x.b) / (x.a - y.a);
    }
    void insert(Line x)
    {
    	while(top)
    	{
    		if(fabs(x.a - stack[top - 1].a) < EPS)
    			top --;
    		else if(top > 1 && (get(x, stack[top - 1]) <= get(stack[top - 1], stack[top - 2])))
    			top --;
    		else
    			break;
    	}
    	stack[top ++] = x;
    }
    int ans[N];
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("BZOJ1007.in", "r", stdin);
    	freopen("BZOJ1007.out", "w", stdout);
    	#endif
    	int n;
    	scanf("%d", &n);
    	for(int i = 0; i < n; i ++)
    		scanf("%f%f", &line[i].a, &line[i].b), line[i].ID = i;
    	sort(line, line + n);
    	top = 0;
    	for(int i = 0; i < n; i ++)
    		insert(line[i]);
    	memset(ans, 0, sizeof(ans));
    	for(int i = 0; i < top; i ++)
    		ans[stack[i].ID] = 1;
    	for(int i = 0; i < n; i ++)
    		if(ans[i])
    			printf("%d ", i + 1);
    }
    
  • 相关阅读:
    代码生成器所用到的东西
    被float.parse吃掉的0.03...
    Microsoft Visual Studio 2010 Ultimate ISO 官方下载地址
    关于.net实现网站模板机制(非标签替换)
    关于ACCESS的事务与存储过程的调用
    关于如何实现左中右三栏布局, 左右固定宽度,中间随屏幕自适应
    几个台湾优秀个人博客网站
    [转]MathType常见问题
    Qt中int转换成QString
    fatal error C1189: #error : The C++ Standard Library forbids macroizing keywords. Enable warning C4005 to find the forbidden macro.
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6482979.html
Copyright © 2020-2023  润新知