题目:给出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("\n");
    }
    return 0;
}
View Code