• hdu6325 Interstellar Travel 变形凸包


    题目:给出n个平面坐标,保证第一个点和第n个点y值为0,其余点的x坐标都在中间,要从 i 点走到 j 点的要求是 i 点的横坐标严格小于 j 的横坐标,并且消耗的能量是(x* y- x* yi),要求消耗的能量最小(能量可以为负),并且字典序要求最小。

    思路:说实话我一开始真没啥思路,最后还是看了题解才知道往凸包上想,菜!大概就是消耗的能量可以是负的,而且该起点为为(0,0)所以x1y2-x2y1等价于所求凸包面积的负值,要想耗费的能量最小,那么就是多边形的面积最大,即凸包!(若第一个点不是(0,0)所有其他的点都减去第一个点的坐标,用相对坐标求即可)求字典序最小的话,就是有可能在一条线段上有多个点,尝试取每一个点,若可以减少字典序,就加进去即可!

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    //#define _for(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    typedef long long ll;
    double eps=0.05;
    ll mod=1e9+7;
    const int INF=0x3f3f3f3f,inf =0x3f3f3f3f;
    const int MAXN=2e3+10;
    const int maxn = 1e7+10;
    const double PI=acos(-1.0);
    //ll inf=100000000000000;
    //template<typename T>inline void read(T &x)
    //{
    //    x=0;
    //    static int p;p=1;
    //    static char c;c=getchar();
    //    while(!isdigit(c)){if(c=='-')p=-1;c=getchar();}
    //    while(isdigit(c)) {x=(x<<1)+(x<<3)+(c-48);c=getchar();}
    //   x*=p;
    //}
    typedef unsigned long long ull;
    const int N=2e5+7;
    struct node{
        int x,y;
        int ps;
        bool operator <(node &p){
        if(x!=p.x)return x<p.x;
        if(y!=p.y)return y>p.y;
        return ps<p.ps;
        }
    }p[N];
    int que[N],mn[N];
    ll cross(int x,int y,int z){
        int ax=p[y].x-p[x].x;
        int ay=p[y].y-p[x].y;
        int bx=p[z].x-p[y].x;
        int by=p[z].y-p[y].y;
        return 1ll*ax*by-1ll*bx*ay;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--){
            int n;
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
                scanf("%d%d",&p[i].x,&p[i].y);
            for(int i=1;i<=n;i++)p[i].ps=i;
            sort(p+1,p+n+1);
            int now=0;
            for(int i=2;i<=n;i++){
                if(p[i].x==p[i-1].x)continue;
                while(now&&cross(que[now-1],que[now],i)>0)now--;
                que[++now]=i;
            }
            int l=0,r;
            printf("1");
            while(l<now){
                for(r=l+1;r<=now;r++){
                    if(cross(que[l],que[l+1],que[r])!=0)break;
                }
                mn[r]=1e9;
                for(int i=r-1;i>=l;i--){
                    mn[i]=min(mn[i+1],p[que[i]].ps);
                }
                for(int i=l+1;i<=r-1;i++){
                    if(mn[i]==p[que[i]].ps)printf(" %d",p[que[i]].ps);
                }
                l=r-1;
            }
            printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    poj 1035 字符串匹配
    拓扑排序的小总结
    POJ1018
    POJ1328详细题解
    POJ1159题解报告
    POJ1088 (滑雪)
    树状树组区间修改,单点修改模板
    spfa模板
    树状树组离散化求逆序对模板
    POJ3723(最小生成树,负权)
  • 原文地址:https://www.cnblogs.com/kayiko/p/13640094.html
Copyright © 2020-2023  润新知