ZOJ 2967 Colorful Rainbows 【Stack】

解决此题方法类似于凸包,先把所有直线按照斜率a由小到大排序
斜率相同取b较大的,扔掉b小的 (可以在遍历的时候忽视)。于是所有直线斜率不同。

准备一个栈 (手动模拟),
栈里面存放上一次能看到的“最上面”的直线以及这条直线能看到的范围x (x值右边的部分可以被看到)。
初始时,把斜率最小的直线入栈,并记录x值为-inf。然后对第i条直线,

所做的是用第i条直线和栈顶直线求交点x,如果这个x值不大于栈顶的x值,
则把栈顶元素弹出,继续求交,否则退出。这种判断操作直到栈为空,
或者当前栈顶的x值大于栈顶的x值。然后把第i条直线入栈,
继续,看后面的直线。最后栈中的直线数就是能看到的。
这种做法类似于凸包的方法,除去排序外,每条直线至多出入栈一次

复杂度O(n)。总复杂度是O(nlogn)。

Source Code:

//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <vector>
#include <algorithm>
#define Max(a,b) (((a) > (b)) ? (a) : (b))
#define Min(a,b) (((a) < (b)) ? (a) : (b))
#define Abs(x) (((x) > 0) ? (x) : (-(x)))
#define MOD 1000000007
#define pi acos(-1.0)

using namespace std;

typedef long long           ll      ;
typedef unsigned long long  ull     ;
typedef unsigned int        uint    ;
typedef unsigned char       uchar   ;

template<class T> inline void checkmin(T &a,T b){if(a>b) a=b;}
template<class T> inline void checkmax(T &a,T b){if(a<b) a=b;}

const double eps = 1e-8         ;
const int N = 210               ;
const int M = 1100011*2         ;
const ll P = 10000000097ll      ;
const int MAXN = 10900000       ;
const double MINN = -999999999.9;

int n;

struct Line{
    double a, b;
}line[5001];

struct Point{
    int ID;
    double x;   //Crossover point
}point[5001];

bool cmp (Line a , Line b){
    if(a.a != b.a)  return a.a < b.a ;
    return a.b > b.b;
}

int main(){
    int i, j, t, k, u, v, numCase = 0;
    cin >> t;
    while (t--){
        int sum = 0;
        cin >> n;
        for (i = 0; i < n; ++i) {
            cin >> line[i].a >> line[i].b;
        }
        sort (line , line + n, cmp);

        point[sum].ID = 0;
        point[sum].x = MINN;

        for (i = 1; i < n; ++i) {
            if (Abs (line[i].a - line[point[sum].ID].a) < eps)    continue; //Equal slope will be ignored
            for (;;) {
                if (sum < 0) {
                    ++sum;
                    point[sum].ID = i;
                    point[sum].x = MINN;
                    break;
                }
                double x = (line[point[sum].ID].b - line[i].b) / (line[i].a - line[point[sum].ID].a);
                if (point[sum].x + eps > x) {
                    --sum;
                } else {
                    ++sum;
                    point[sum].ID = i;
                    point[sum].x = x;
                    break;
                }
            }
        }
        printf("%d\n", 1 + sum);
     }

     return 0 ;
}
时间: 2024-10-21 20:55:59

ZOJ 2967 Colorful Rainbows 【Stack】的相关文章

zoj 2967 Colorful Rainbows (堆栈应用)

题意:给出n条y=ai*x+bi的直线.对于这些直线,如果存在x使得该直线y大于其他任意一直线,那么这条直线可以被看见,问有多少条直线可以被看见. 思路:首先去重,将那些a值相同的直线取其中b最大的那条保留下来,其他的全删掉. 其次将直线按照a值从小到大排序,因为斜率不同,所以任意两条直线都会相交.而这些直线是按照斜率从小到大进行排序,所以当x小于其交点x值时,斜率小的y值大. 利用这一特性将,先让线入栈.若将入栈的线与栈顶线的交点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

POJ1363 Rails【stack】【栈】

Rails Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 25638 Accepted: 10068 Description There is a famous railway station in PopPush City. Country there is incredibly hilly. The station was built in last century. Unfortunately, funds were

ZOJ 1671:Walking Ant【bfs】

Walking Ant Time Limit: 2 Seconds      Memory Limit: 65536 KB Ants are quite diligent. They sometimes build their nests beneath flagstones. Here, an ant is walking in a rectangular area tiled with square flagstones, seeking the only hole leading to h

Zoj 3598 Spherical Triangle 【计算几何】【曲面三角形】

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3598 题目大意:给出一个球体上的三点,三点的坐标以经纬度的形式给出,求曲面三角形的内角和. 即:给出ABC三个点的经纬度,求出 角A+ 角B+角C的值. 利用公式即可求得 cosa=cosb*cosc+sinb*sinc*cosA 其中小写a,b,c表示球面三角形边长所对应的圆心角 大写A表示三角形内角. 下面的难度就是求出abc角的大小即可. 网上看了一个写法

【练习赛2补题】zoj 2734 Exchange Cards 【DFS】

As a basketball fan, Mike is also fond of collecting basketball player cards. But as a student, he can not always get the money to buy new cards, so sometimes he will exchange with his friends for cards he likes. Of course, different cards have diffe

zoj 3622 Magic Number 【规律】

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3622 题目大意: 如果一个数字x满足如下条件: 任意加一个数字y在x的左边,都能是yx是x的倍数,比如1满足,2满足,5满足条件. 然后最开始以为1 2 5 的十倍数10 20 50 , 100 200 500 以及很多,然后后来发现了一个bug就是25 ,发现找的规律是有问题的. 后来发现是10 100 1000 10000 分别除以1 2 3 4 5 6 7

局部变量、全局变量、堆、堆栈、静态和全局【转】

转自:http://blog.csdn.net/jeffade/article/details/7958013 预备知识—程序的内存分配 一个由C/C++编译的程序占用的内存分为以下几个部分 栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈. 堆区(heap) — 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 .注意它与数据结构中的堆是两回事,分配方式倒是类似于链表. 全局区(静态区)(static)—,全局变量和静态

【C++】Stack类与Queue类学习

1.Stack类学习 1)建立stack<string> 2)调用push函数将数据压入栈中 3)调用size函数查看当前栈内元素数量 4)调用empty函数检测栈是否为空 5)如果不为空则不断调用pop函数将元素从栈中取出(后入先出) #include <iostream> #include <stack> using namespace std; int main() {     stack<string> stkNameList;     stkNam