UVALive 4992 Jungle Outpost(半平面交)

题意:给你n个塔(点)形成一个顺时针的凸包,敌人可以摧毁任何塔,摧毁后剩下的塔再组成凸包

   在开始的凸包内选一点为主塔,保证敌人摧毁尽量多塔时主塔都还在现在的凸包内,求出最多摧毁的塔

题解:这题关键就是选的主塔在不同的地方,敌人就会摧毁不同的塔来让你的主塔暴露

因此这样想,找出敌人摧毁不同的塔后形成的所有不同的凸包,再求出所有凸包的交就好

具体就是,首先枚举摧毁塔的个数k,再把摧毁任意k个塔所形成的所有不同的凸包求一个交,如果为空就代表了摧毁k个塔一定可以保证无论主塔在哪儿都可以暴露(关键)

而所有凸包的交可以将其转化为找到所有凸包上的直线求半平面交,接着就是注意敌人摧毁连续的k个塔一定是最优的,所以求半平面交的直线只要n条(理解一下)

最后可以发现答案满足单调性,可以二分答案

再然后这儿有个小trick就是找直线时需要逆时针找(因为半平面交是逆时针来求的)

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=1<<28;
const ll INF=1ll<<60;
const double Pi=acos(-1.0);
const int Mod=1e9+7;
const int Max=50010;
struct Point
{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y) {};
    int read()
    {
        scanf("%lf%lf",&x,&y);
    }
    inline Point operator+(const Point& a)const
    {
        return Point(x+a.x,y+a.y);
    }
    inline Point operator*(double a)const
    {
        return Point(x*a,y*a);
    }
    inline Point operator-(const Point& a)const
    {
        return Point(x-a.x,y-a.y);
    }
    inline bool operator<(const Point& a)const
    {
        return sgn(x-a.x)<0||zero(x-a.x)&&sgn(y-a.y)<0;
    }
    inline bool operator!=(const Point& a)const
    {
        return !(zero(x-a.x)&&zero(y-a.y));
    }
};
typedef Point Vector;
struct Line
{
    Point p;
    Vector v;
    double ang;//极角
    Line() {};
    Line(Point p,Vector v):p(p),v(v)
    {
        ang=atan2(v.y,v.x);
    }
    inline bool operator<(const Line& L)const
    {
        return ang<L.ang;
    }
};
double Dis(Point A,Point B)
{
    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
double Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}
bool OnLeft(Line L,Point p)
{
    return Cross(L.v,p-L.p)>0;
}
Point GetIntersection(Line a,Line b)
{
    Vector u=a.p-b.p;
    double t=Cross(b.v,u)/Cross(a.v,b.v);
    return a.p+a.v*t;
}
int HarfplaneIntersection(Line *L,int n)
{
    sort(L,L+n);
//        for(int i=0; i<n; ++i)
//    {
//        printf("%lf %lf %lf %lf\n",L[i].p.x,L[i].p.y,L[i].v.x,L[i].v.y);
//    }
    int first,last;
    Point *p=new Point[n];
    Line *q=new Line[n];
    q[first=last=0]=L[0];
    for(int i=0; i<n; ++i)
    {
        while(first<last && !OnLeft(L[i],p[last-1])) last--;
        while(first<last && !OnLeft(L[i],p[first])) first++;
        q[++last]=L[i];
        if(zero(Cross(q[last].v,q[last-1].v)))
        {
            last--;
            if(OnLeft(q[last],L[i].p))
                q[last]=L[i];
        }
        if(first<last)
            p[last-1]=GetIntersection(q[last-1],q[last]);
    }
    while(first<last&&!OnLeft(q[first],p[last-1]))
        last--;
//        printf("%d\n",last-first-1);
    return max(last-first-1,0);
}
Point tow[Max];
Line convex[Max];
int Solve(int mid,int n)
{
    if(n-mid<=2)//剩余的点
        return 0;
    for(int i=0; i<n; ++i)
    {
        //注意注意,半平面交为逆时针
        convex[i]=Line(tow[i],tow[(i-mid-1+n)%n]-tow[i]);//关键,删除了mid个点后的半平面
    }
    return HarfplaneIntersection(convex,n);
}
int Dichotomy(int lef,int rig,int n)//二分
{
    while(lef<rig)
    {
        int mid=(lef+rig>>1);//代表删多少个点
        if(Solve(mid,n))//非空即为需要删除更多的点
        {
            lef=mid+1;
        }
        else
        {
            rig=mid;
        }
    }
    return lef;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0; i<n; ++i)
        {
            tow[i].read();
        }
        printf("%d\n",Dichotomy(1,n,n));
    }
    return 0;
}
时间: 2024-11-08 19:04:18

UVALive 4992 Jungle Outpost(半平面交)的相关文章

UVALive 4992 Jungle Outpost(半平面交判存)

Jungle Outpost Time limit: 15.000 seconds Description There is a military base lost deep in the jungle. It is surrounded by n watchtowers with ultrasonic generators. In this problem watchtowers are represented by points on a plane. Watchtowers genera

uvalive 7331 Hovering Hornet 半平面交+概率期望

题意:一个骰子在一个人正方形内,蜜蜂在任意一个位置可以出现,问看到点数的期望. 思路:半平面交+概率期望 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdlib> 6 #include<string> 7 #include<cmath> 8 #include<vector&

UVa 1475 (二分+半平面交) Jungle Outpost

题意: 有n个瞭望塔构成一个凸n边形,敌人会炸毁一些瞭望台,剩下的瞭望台构成新的凸包.在凸多边形内部选择一个点作为总部,使得敌人需要炸毁的瞭望塔最多才能使总部暴露出来.输出敌人需要炸毁的数目. 分析: 在炸毁同样数量的瞭望塔时,如何爆破才能使暴露出的面积最大.那就是集中火力炸掉连续的几个瞭望塔.直觉上是这样的,我不会证明这个结论.因为是连续爆破,所以k次爆破后还保留的部分就是一个半平面,枚举这k个爆破点,如果这些半平面交非空则总部可以设在这里. k值是通过二分来确定的,下界是1,上界是n-3(这

UVA 1475 - Jungle Outpost(二分 + 半平面交)

题目链接:点击打开链接 思路:首先,我们要知道一个贪心结论:敌人如果有k个炸弹, 那么他一定是炸连续的k个点, 这样会使得炸的面积最大.  那么我们只要二分炸弹数mid,每隔mid个点重新建立一个平面, 仍然是n个平面, 代表n种可能情况, 那么如果他们的交存在, 那么司令部只要放在这个平面交的面积内就行了.  所以问题迎刃而解, 二分答案, 用半平面交判断答案是否可行. 细节参见代码: #include <cstdio> #include <cstring> #include &

LA 2218 (半平面交) Triathlon

题意: 有n个选手,铁人三项有连续的三段,对于每段场地选手i分别以vi, ui 和 wi匀速通过. 对于每个选手,问能否通过调整每种赛道的长度使得他成为冠军(不能并列). 分析: 粗一看,这不像一道计算几何的题目. 假设赛道总长度是1,第一段长x,第二段长y,第三段则是1-x-y 那么可以计算出每个选手完成比赛的时间Ti 对于选手i,若要成为冠军则有Ti < Tj (i ≠ j) 于是就有n-1个不等式,每个不等式都代表一个半平面. 在加上x>0, y>0, 1-x-y>0 这三个

POJ3525-Most Distant Point from the Sea(二分+半平面交)

Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3955   Accepted: 1847   Special Judge Description The main land of Japan called Honshu is an island surrounded by the sea. In such an island, it is natural t

bzoj 1007 水平可见直线 半平面交稀里糊涂的过了...

题意:按y=Ax+B的形式给出n(<=50000)条直线,求从y值为无穷大的地方向下看能看到的直线编号 一看到题目就想到半平面交,以每条直线的上方为一个半平面,求半平面的交,交集中存在的直线就是能看到的直线 但是写出来之后发现样例都过不了... 对于样例,如果允许半平面在边界处重叠那么答案是1,2,3,如果不允许只有1.. 然后抱着试一试的心理交上去了,结果竟然直接AC了.. 后来看题解只需要考虑交点x坐标.. bzoj 1007 水平可见直线 半平面交稀里糊涂的过了...,布布扣,bubuko

POJ 2540 半平面交求可行区域面积

Hotter Colder Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2343   Accepted: 981 Description The children's game Hotter Colder is played as follows. Player A leaves the room while player B hides an object somewhere in the room. Player

poj 3525 Most Distant Point from the Sea 半平面交 + 二分

题目来源: http://poj.org/problem?id=3525 分析: 题意:给定一个凸多边形,求多边形中距离边界最远的点到边界的距离. 思路 : 每次将凸多边形每条边往里平移d,判断是否存在核:二分d即可. 多边形边上的点(x , y)往里平移d 后的 坐标: s , e  为向量的 起点和终点, len 为起点和终点的距离, h 为平移的距离 x' = x + dx y' = y + dy dx = ( s.y - e.y ) / len * h ,( 原理 是 利用 三角形的相似