解决此题方法类似于凸包,先把所有直线按照斜率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