按斜率排序,斜率线相同的直线取截距最大的
一条直线能够被看到的条件是,与比它斜率小的交点在比它斜率大的交点的左侧
1007: [HNOI2008]水平可见直线
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4234 Solved: 1558
[ Submit][ Status][ Discuss]
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
-1 0
1 0
0 0
Sample Output
1 2
HINT
C++:
/* ***********************************************
Author :CKboss
Created Time :2015年05月10日 星期日 08时38分36秒
File Name :BZOJ1007.cpp
************************************************ */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
const int maxn=50500;
int n;
struct Line
{
int id;
int k,b;
}line[maxn];
bool cmp(Line A,Line B)
{
if(A.k!=B.k) return A.k<B.k;
return A.b>B.b;
}
Line stack[maxn];
int st;
double cal(Line X,Line Y) /// Line X < Line Y
{
return (double)(Y.b-X.b)/(X.k-Y.k);
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
line[i]=(Line){i+1,x,y};
}
sort(line,line+n,cmp);
int m=0;
int lastk=8888888;
for(int i=0;i<n;i++)
{
if(lastk!=line[i].k)
{
line[m++]=line[i];
lastk=line[i].k;
}
}
n=m;
stack[st++]=line[0];
for(int i=1;i<n;i++)
{
while(st>1&&cal(stack[st-2],stack[st-1])>=cal(stack[st-1],line[i]))
st--;
stack[st++]=line[i];
}
vector<int> v;
for(int i=0;i<st;i++) v.push_back(stack[i].id);
sort(v.begin(),v.end());
for(int i=0;i<st;i++)
printf("%d ",v[i]);
putchar(10);
return 0;
}
JAVA:
import java.util.*;
public class Main {
final int maxn=50500;
final double eps = 1e-7;
int n;
public class Line{
public int k,b,id;
}
public class cmp1 implements Comparator{
public int compare(Object x,Object y){
Line A=(Line)x,B=(Line)y;
if(A.k!=B.k) return A.k-B.k;
return B.b-A.b;
}
}
Line[] line=new Line[maxn];
double CAL(Line A,Line B){
return (double)(B.b-A.b)/(A.k-B.k);
}
Line[] Stack=new Line[maxn];
int st;
public Main() {
Scanner in = new Scanner(System.in);
n=in.nextInt();
for(int i=0;i<n;i++){
line[i]=new Line();
line[i].k=in.nextInt();
line[i].b=in.nextInt();
line[i].id=i+1;
}
Arrays.sort(line,0,n,new cmp1());
int last=888888;
int m=0;
for(int i=0;i<n;i++){
if(line[i].k!=last){
line[m++]=line[i];
last=line[i].k;
}
}
n=m;
Stack[0]=line[0]; st=1;
for(int i=1;i<n;i++){
while(st>1&&CAL(Stack[st-1],Stack[st-2])>=CAL(Stack[st-1],line[i]))
st--;
Stack[st++]=line[i];
}
Vector vi=new Vector<Integer>();
for(int i=0;i<st;i++){
vi.add(Stack[i].id);
}
Collections.sort(vi);
for(int i=0;i<st;i++){
System.out.printf("%d ",vi.get(i));
}
}
public static void main(String[] args){
new Main();
}
}