• HDU 2907


    题意略。

    思路:求出凸包后,ans = 在凸包上的边 * q - 凹陷个数 * p。

                  

    一条边上,一个端点在凸包上,另一个端点在凸包内,则一定是凹陷的一条边,我们单向地来扫这些边,记录第一个点在凸包上,而第二个点不在凸包上的边的

    个数,这些记录的总和也就是凹陷的总数。由于一个凹陷总是可以被凸包上的一条边覆盖住,所以我们最终的答案也可以表示为:

    凸包上的边数 * q - 凹陷数 * q(不该加上) - 凹陷数 * p

    详见代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 50;
    const double eps = 1e-6;
    
    struct Point{
        double x,y;
        int id;
        Point(double a = 0,double b = 0){
            x = a,y = b;
        }
        Point operator -(const Point& b) const{
            return Point(x - b.x,y - b.y);
        }
        double operator ^(const Point& b) const{
            return x * b.y - y * b.x;
        }
        double operator *(const Point& b) const{
            return x * b.x + y * b.y;
        }
    };
    struct line{
        Point bg,ed;
        line(){}
        line(Point a,Point b){
            bg = a,ed = b;
        }
    };
    
    Point List[maxn];
    int Stack[maxn],top,ison[maxn];
    
    int sgn(double f){
        if(fabs(f) < eps) return 0;
        else if(f < 0) return -1;
        else return 1;
    }
    double dist(Point p1,Point p2){
        double dx = p1.x - p2.x;
        double dy = p1.y - p2.y;
        return sqrt(dx * dx + dy * dy);
    }
    bool cmp(const Point& p1,const Point& p2){
        double tmp = (p1 - List[0]) ^ (p2 - List[0]);
        if(sgn(tmp) > 0) return true;
        else if(sgn(tmp) == 0 && sgn(dist(p1,List[0]) - dist(p2,List[0])) <= 0) return true;
        return false;
    }
    void Graham(int n){
        Point p0;
        int k = 0;
        p0 = List[0];
        for(int i = 1;i < n;++i){
            if((p0.y > List[i].y) || (p0.y == List[i].y && p0.x > List[i].x)){
                p0 = List[i];
                k = i;
            }
        }
        swap(List[k],List[0]);
        sort(List + 1,List + n,cmp);
        if(n == 1){
            top = 1;
            Stack[0] = 0;
            return;
        }
        if(n == 2){
            top = 2;
            Stack[0] = 0;
            Stack[1] = 1;
            return;
        }
        Stack[0] = 0;
        Stack[1] = 1;
        top = 2;
        for(int i = 2;i < n;++i){
            while(top > 1 && sgn((List[Stack[top - 1]] - List[Stack[top - 2]]) ^ (List[i] - List[Stack[top - 2]])) <= 0)
                --top;
            Stack[top++] = i;
        }
    }
    
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            int p,q,n;
            top = 0;
            memset(ison,0,sizeof(ison));
            scanf("%d%d%d",&p,&q,&n);
            for(int i = 0;i < n;++i){
                scanf("%lf%lf",&List[i].x,&List[i].y);
                List[i].id = i;
            }
            int ans = 0;
            int cnt = 0;
            Graham(n);
            for(int i = 0;i < top;++i){
                ison[List[Stack[i]].id] = 1;
            }
            ison[n] = ison[0];
            for(int i = 0;i < n;++i){
                if(ison[i] == 1 && ison[i + 1] == 0)
                {
                    ++cnt;
                }
            }
            ans = top * q - cnt * p - cnt * q;
            printf("%d
    ",max(ans,0));
        }
        return 0;
    }
    
    /*
    1 
    10 5 7
    0 10
    8 4
    10 -7
    6 -9
    -5 -4
    -5 7
    -2 6
    
    15
    */
    
    /*
    1
    10 5 8
    0 8
    0 10
    8 4
    10 -7
    6 -9
    -5 -4
    -5 7
    -2 6
    
    15
    */
  • 相关阅读:
    jumperserver3.0的安装部署
    zookeeper3.4.6配置实现自动清理日志
    因为修改linux selinux修改错误产生的问题及解决办法
    修改linux系统编码
    linux如何连接移动硬盘
    调整linux系统时区
    关于公司夫妻档的事情
    hive将数据导致本地磁盘
    shell如何向python传递参数,shell如何接受python的返回值
    关于日志API接口中流量的使用。
  • 原文地址:https://www.cnblogs.com/tiberius/p/9292861.html
Copyright © 2020-2023  润新知