【栈】bzoj 1007 水平可见直线

来源:互联网 发布:网络安全员年薪多少 编辑:程序博客网 时间:2024/06/05 10:58

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1007
题目大意:某个坐标系上有一坨直线,每根直线都表示为kx+b的形式,如果在任意时刻直线i位于最上方,则直线i是可见的,求所有可见直线的编号

这个居然是考试题,惊了
乱搞做法:
开始完全没有任何想法……但是会发现:任意两条k不同的直线都会有一个交点,于是我就脑洞出了做法……首先按k从小到大排序,k相同的留下b最大的一条即可,然后开始暴力找……
找到第一条,然后从它后面的找出一条和它相交最早的一条直线,如果有多条直线在同一时刻和它相交,只留那条k最大的,然后再把找到的这条直线作为开始的直线,再次向后暴力找(前面的不用管了),重复刚才的做法……直至找不到一条可以超过它的直线为止
时间复杂度O(n^2-出题人的良心) bzoj可AC233333
代码:

#include <iostream>#include <cstdio>#include <algorithm>#define INF 2147483647using namespace std;struct man{    int k,b,s;}a[200000];int ans[200000];bool cmp(man x,man y){    if(x.k != y.k)        return x.k < y.k;    return x.b < y.b;}int main(){    int n,cnt = 0,maxn = 0;    scanf("%d",&n);    for(int i = 1;i <= n;i ++)    {        scanf("%d%d",&a[i].k,&a[i].b);        a[i].s = i;    }    sort(a+1,a+n+1,cmp);    for(int i = 1;i ;i )    {        while(a[i+1].k == a[i].k)            i ++;        ans[++cnt] = a[i].s;        int k = 0;        double fast = INF;        for(int j = i+1;j <= n;j ++)        {            double time = (double)(a[j].b - a[i].b)/(a[i].k - a[j].k);            if(time <= fast)            {                fast = time;                k = j;            }        }        i = k;    }    sort(ans+1,ans+cnt+1);    for(int i = 1;i <= cnt;i ++)        cout << ans[i] << " ";    return 0;}

正确做法:按k从小到大排序,开一个栈,如果下一条直线与top-1的交点横坐标小于与top交点的横坐标,那么就直接删除top,最后栈中的就是答案
代码?不要随便伸手要代码,自己能打出来不是更好吗?再说这题又不是很难(明明是你自己懒打好吗)

1 0
原创粉丝点击