zoukankan      html  css  js  c++  java
  • hdu6325 Interstellar Travel 凸包变形

    题目传送门

    题目大意:

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

    思路:

          消耗能量的式子就是两个坐标的叉积,叉积的几何意义就是两个向量对应的平行四边形的面积,但是这个面积会有正负,如果向量 j 在向量 i 的顺时针方向,则这个面积是负的,如果我希望能量最小,那么就尽可能使向量是顺时针方向的,由此发现其实就得到了一个凸包,而且是一个上凸包。经过凸包上的点都符合能量的要求,但是由于要求字典序最小,所以如果凸包上的某一条边上有很多点,那么就需要判断一下这些点的id,如果线段中间的点的id比较小,那么这些点选上了之后,字典序肯定会变小,所以在做凸包的时候就要对凸包算法加一点点变形。

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<map>
    #include<set>
    #include<cstring>
    #include<queue>
    #include<stack>
    #define CLR(a,b) memset(a,b,sizeof(a))
    #define mkp(a,b) make_pair(a,b)
    typedef long long ll;
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int maxn = 200010;
    struct dian {
        double x, y;
        int id;
        dian (){}
        dian(double x, double y, int id) :x(x), y(y), id(id){}
    }a[maxn],ch[maxn];
    bool cmp(dian &a, dian &b)
    {
        if (a.x - b.x) return a.x < b.x;
        if (a.y - b.y) return a.y < b.y;
        return a.id < b.id;
    }
    typedef dian Vector;
    Vector operator -(Vector a, Vector b) {
        return Vector ( a.x - b.x, a.y - b.y,0 );
    }
    bool operator == (Vector a,Vector b){
        return ((a.x==b.x) && (a.y==b.y));
    }
    double cross(Vector a, Vector b)
    {
        return a.x*b.y - a.y*b.x;
    }
    int andrew(dian *p, int n, dian *ch)
    {
        int m = 0;
        sort(p, p + n, cmp);
        for (int i = 0; i < n; i++)
        {
            if(i>0&&p[i]==ch[m-1])continue;
            while (m > 1 && cross(ch[m - 2] - ch[m - 1], p[i] - ch[m - 1] )<= 0)
            {
                if(cross(ch[m - 2] - ch[m - 1], p[i] - ch[m - 1] )< 0)
                m--;
                else if(ch[m-1].id>p[i].id){
                    m--;
                }else break;
            }
            ch[m++] = p[i];
        }
        return m;
    }    
    bool vis[maxn];
    int main() {
        int n,T;
        cin >> T;
        while (T--)
        {
            CLR(vis, inf);
            scanf("%d", &n);
            for (int i = 0; i < n; i++)
            {
                scanf("%lf%lf", &a[i].x, &a[i].y);
                a[i].id = i+1;
            }
            int m = andrew(a, n, ch);
            for (int i = 0; i<=m-1; i++)
            {
                printf("%d", ch[i].id);
                if (i < m-1)printf(" ");
                else printf("
    ");
            }
        }
        
    
    }
    
    /*
    
    1
    7
    0 0
    9 0
    3 6
    1 2
    3 6
    2 4
    10 0
    
    
    */

    Problem G. Interstellar Travel

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
    Total Submission(s): 2098    Accepted Submission(s): 544


    Problem Description
    After trying hard for many years, Little Q has finally received an astronaut license. To celebrate the fact, he intends to buy himself a spaceship and make an interstellar travel.
    Little Q knows the position of n planets in space, labeled by 1 to n. To his surprise, these planets are all coplanar. So to simplify, Little Q put these n planets on a plane coordinate system, and calculated the coordinate of each planet (xi,yi).
    Little Q plans to start his journey at the 1-th planet, and end at the n-th planet. When he is at the i-th planet, he can next fly to the j-th planet only if xi<xj, which will cost his spaceship xi×yjxj×yi units of energy. Note that this cost can be negative, it means the flight will supply his spaceship.
    Please write a program to help Little Q find the best route with minimum total cost.
     
    Input
    The first line of the input contains an integer T(1T10), denoting the number of test cases.
    In each test case, there is an integer n(2n200000) in the first line, denoting the number of planets.
    For the next n lines, each line contains 2 integers xi,yi(0xi,yi109), denoting the coordinate of the i-th planet. Note that different planets may have the same coordinate because they are too close to each other. It is guaranteed that y1=yn=0,0=x1<x2,x3,...,xn1<xn.
     
    Output
    For each test case, print a single line containing several distinct integers p1,p2,...,pm(1pin), denoting the route you chosen is p1p2...pm1pm. Obviously p1 should be 1 and pm should be n. You should choose the route with minimum total cost. If there are multiple best routes, please choose the one with the smallest lexicographically.
    A sequence of integers a is lexicographically smaller than a sequence of b if there exists such index j that ai=bi for all i<j, but aj<bj.
     
    Sample Input
    1 3 0 0 3 0 4 0
     
    Sample Output
    1 2 3
     
    Source
  • 相关阅读:
    Mybatis 原始dao CRUD方法
    JQuery的焦点事件focus() 与按键事件keydown() 及js判断当前页面是否为顶级页面 子页面刷新将顶级页面刷新 window.top.location
    使用actionerror做失败登录验证
    Java项目中的下载 与 上传
    shiro框架 4种授权方式 说明
    javascript 中数组的创建 添加 与将数组转换成字符串 页面三种提交请求的方式
    序列化表单为json对象,datagrid带额外参提交一次查询 后台用Spring data JPA 实现带条件的分页查询 多表关联查询
    Spring data JPA 理解(默认查询 自定义查询 分页查询)及no session 三种处理方法
    orcal 数据库 maven架构 ssh框架 的全注解环境模版 maven中央仓库批量删除lastupdated文件后依然是lastupdated解决方法 mirror aliyun中央仓库
    EasyUI加zTree使用解析 easyui修改操作的表单回显方法 验证框提交表单前验证 datagrid的load方法
  • 原文地址:https://www.cnblogs.com/mountaink/p/9591414.html
Copyright © 2011-2022 走看看