zoj 2967 Colorful Rainbows (堆栈应用)

题意:给出n条y=ai*x+bi的直线。对于这些直线,如果存在x使得该直线y大于其他任意一直线,那么这条直线可以被看见,问有多少条直线可以被看见。

思路:首先去重,将那些a值相同的直线取其中b最大的那条保留下来,其他的全删掉。

其次将直线按照a值从小到大排序,因为斜率不同,所以任意两条直线都会相交。而这些直线是按照斜率从小到大进行排序,所以当x小于其交点x值时,斜率小的y值大。

利用这一特性将,先让线入栈。若将入栈的线与栈顶线的交点x值小于栈顶两条线的的交点的x值,则将栈顶线出栈,继续进行上一次判断,知道所有线都判定过。

# include <stdio.h>
# include <algorithm>
# include <iostream>
# include <string.h>
using namespace std;
struct node
{
    double a;
    double b;
};
struct node s[5010],x[5010];
bool cmp(node a1,node a2)
{
    if(a1.a!=a2.a)
        return a1.a<a2.a;
    return a1.b<a2.b;
}
int main()
{
    int t,n,i,cot,ans;
    double d,p;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=0; i<n; i++)
            scanf("%lf%lf",&s[i].a,&s[i].b);
        sort(s,s+n,cmp);
        cot=0;
        for(i=0; i<n-1; i++) ///去重
        {
            if(s[i].a==s[i+1].a)
                continue;
            s[cot++]=s[i];
        }
        s[cot++]=s[n-1];
        if(cot<2)
            printf("%d\n",cot);
        else
        {

            x[1]=s[1];
            x[0]=s[0];
            d=(s[1].b-s[0].b)*1.0/(s[0].a-s[1].a);///第一个交点
            ans=2;
            for(i=2; i<cot; i++)
            {
                p=(s[i].b-x[ans-1].b)*1.0/(x[ans-1].a-s[i].a);
                while(p<=d)///看不见 一直和栈定交点比
                {
                    ans--;
                    if(ans>1)
                    {
                        d=(x[ans-1].b-x[ans-2].b)*1.0/(x[ans-2].a-x[ans-1].a);
                        p=(s[i].b-x[ans-1].b)*1.0/(x[ans-1].a-s[i].a);
                    }
                    else
                    {
                        p=(s[i].b-x[ans-1].b)*1.0/(x[ans-1].a-s[i].a);
                        break;
                    }

                }
                x[ans++]=s[i];
                d=p;
            }
            printf("%d\n",ans);
        }

    }
    return 0;
}
时间: 2024-10-05 05:41:48

zoj 2967 Colorful Rainbows (堆栈应用)的相关文章

ZOJ 2967 Colorful Rainbows 【Stack】

解决此题方法类似于凸包,先把所有直线按照斜率a由小到大排序 斜率相同取b较大的,扔掉b小的 (可以在遍历的时候忽视).于是所有直线斜率不同. 准备一个栈 (手动模拟), 栈里面存放上一次能看到的“最上面”的直线以及这条直线能看到的范围x (x值右边的部分可以被看到). 初始时,把斜率最小的直线入栈,并记录x值为-inf.然后对第i条直线, 所做的是用第i条直线和栈顶直线求交点x,如果这个x值不大于栈顶的x值, 则把栈顶元素弹出,继续求交,否则退出.这种判断操作直到栈为空, 或者当前栈顶的x值大于

ZOJ 3967 Colorful Rainbows --栈的应用

题意:给出n条y=ai*x+bi的直线.对于这些直线,如果存在x使得该直线y大于其他任意一直线,那么这条直线可以被看见,问有多少条直线可以被看见. 做法什么的不讲了,参见:http://blog.csdn.net/ten_three/article/details/12289427  以及  http://blog.sina.com.cn/s/blog_7eee8bf3010136d8.html 利用了堆栈来做,总体复杂度O(nlogn) 代码: #include <iostream> #in

杭电ACM分类

杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDIATE DECODABILITY

【转】对于杭电OJ题目的分类

[好像博客园不能直接转载,所以我复制过来了..] 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDI

转载:hdu 题目分类 (侵删)

转载:from http://blog.csdn.net/qq_28236309/article/details/47818349 基础题:1000.1001.1004.1005.1008.1012.1013.1014.1017.1019.1021.1028.1029. 1032.1037.1040.1048.1056.1058.1061.1070.1076.1089.1090.1091.1092.1093. 1094.1095.1096.1097.1098.1106.1108.1157.116

ZOJ 3435 Ideal Puzzle Bobble

ZOJ Problem Set - 3435 Ideal Puzzle Bobble Time Limit: 2 Seconds      Memory Limit: 65536 KB Have you ever played Puzzle Bobble, a very famous PC game? In this game, as a very cute bobble dragon, you must keep shooting powerful bubbles to crush all t

poj 2246 递归 zoj 1094

#include <iostream>#include <algorithm>#include <stdio.h>#include <string.h>#include <cmath>#include <stack>using namespace std;struct node{ int m,n; // bool f;};node hash[200];char s[1000];int main(){ int i,n,sum; char

ZOJ 1004 Anagrams by Stack

Anagrams by Stack 题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1004 题意:通过堆栈实现将一个字符串转变成目标字符串的操作,要求输出全部的可能操作组合. 思路:利用深度优先的搜索思路,对于每一个状态都有入栈和出栈两种可能的操作,由于要求按字典序输出,每次先考虑入栈再考虑出栈.即"能入就入,不能入考虑是否能退,随后返回上一步". 下面贴代码: 1 //Problem Name: A

PAT-l3-002堆栈

L3-002. 堆栈 大家都知道"堆栈"是一种"先进后出"的线性结构,基本操作有"入栈"(将新元素插入栈顶)和"出栈"(将栈顶元素的值返回并从堆栈中将其删除).现请你实现一种特殊的堆栈,它多了一种操作叫"查中值",即返回堆栈中所有元素的中值.对于N个元素,若N是偶数,则中值定义为第N/2个最小元:若N是奇数,则中值定义为第(N+1)/2个最小元. 输入格式: 输入第一行给出正整数N(<= 105).随