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

题目链接:点击打开链接

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

细节参见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 50000 + 10;
int T,n,m;
struct point {
    double x, y;
    point(double x=0, double y=0):x(x), y(y) {}
};
typedef point Vector;
Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
Vector operator - (Vector A, Vector B) { return Vector(A.x-B.x, A.y-B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
bool operator < (const point& a, const point& b) {
    return a.x < b.x || (a.x == b.x && a.y < b.y);
}
int dcmp(double x) {
    if(fabs(x) < eps) return 0;
    else return x < 0 ? -1 : 1;
}
bool operator == (const point& a, const point& b) {
    return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}
double cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }
double Length(Vector A) { return sqrt(Dot(A, A)); }
Vector Normal(Vector A) {
    double L = Length(A);
    return Vector(-A.y/L, A.x/L);
}
struct Line {
    point p;
    Vector v;
    double ang;
    Line() {}
    Line(point p, Vector v) : p(p), v(v) { ang = atan2(v.y, v.x); }
    bool operator < (const Line& L) const {
        return ang < L.ang;
    }
};
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 halfplane(Line* L, int n, point* poly) {
    sort(L, L+n);
    int first, last;
    point *p = new point[n];
    Line *q = new Line[n];
    q[first=last=0] = L[0];
    for(int i = 1; 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(fabs(cross(q[last].v, q[last-1].v)) < eps) {
            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--;
    if(last - first <= 1) return 0;
    p[last] = getintersection(q[last], q[first]);
    int m = 0;
    for(int i = first; i <= last; i++) poly[m++] = p[i];
    return m;
}
point p[maxn], poly[maxn];
Line L[maxn];
double x, y;
int main() {
    while(~scanf("%d",&n) && n) {
        for(int i = 0; i < n; i++) {
            scanf("%lf%lf",&x,&y);
            p[i] = point(x, y);
        }
        int l = 1, r = n - 1;
        while(r > l) {
            int mid = (r + l) / 2;
            for(int i = 0; i < n; i++) L[i] = Line(p[i], p[i] - p[(i+mid+1)%n]);
            int m = halfplane(L, n, poly);
            if(!m) r = mid;
            else l = mid+1;
        }
        printf("%d\n", l);
    }
    return 0;
}
时间: 2024-10-29 16:19:42

UVA 1475 - Jungle Outpost(二分 + 半平面交)的相关文章

UVALive 4992 Jungle Outpost(半平面交)

题意:给你n个塔(点)形成一个顺时针的凸包,敌人可以摧毁任何塔,摧毁后剩下的塔再组成凸包 在开始的凸包内选一点为主塔,保证敌人摧毁尽量多塔时主塔都还在现在的凸包内,求出最多摧毁的塔 题解:这题关键就是选的主塔在不同的地方,敌人就会摧毁不同的塔来让你的主塔暴露 因此这样想,找出敌人摧毁不同的塔后形成的所有不同的凸包,再求出所有凸包的交就好 具体就是,首先枚举摧毁塔的个数k,再把摧毁任意k个塔所形成的所有不同的凸包求一个交,如果为空就代表了摧毁k个塔一定可以保证无论主塔在哪儿都可以暴露(关键) 而所

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

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

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

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

相当于多边形内最大圆,二分半径r,然后把每条边内收r,求是否有半平面交(即是否合法) #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; const int N=205; const double eps=1e-6; int n; struct dian { double x,y; dian(double X=0,double

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

pro:给定凸多边形,求凸多边形内的点到最近边界的最远距离. sol:显然是二分一个圆,使得圆和凸多边形不相交,但是这样很难实现. 由于是凸多边形,我们可以把二分圆转化为二分凸多边形的移动. 如果每一边向左移动Mid后,任然存在“核”,则表示存在一点合法. 直线移动:移动起点即可,方向不变. #include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespa

poj3525Most Distant Point from the Sea(半平面交)

链接 求凸多边形内一点距离边最远. 做法:二分+半平面交判定. 二分距离,每次让每条边向内推进d,用半平面交判定一下是否有核. 本想自己写一个向内推进..仔细一看发现自己的平面交模板上自带.. 1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector>

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

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 ,( 原理 是 利用 三角形的相似

UVA 3890 Most Distant Point from the Sea(二分法+半平面交)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11358 [思路] 二分法+半平面交 二分与海边的的距离,由法向量可以得到平移后的各边,半平面交在特定精度判断是否有交集. [代码] 1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace s