2018 Multi-University Training Contest 3G-HDU6325(凸包)

题意:选取多个点从第一个点到达第n个点并且要求满足条件横坐标是递增的,相邻两点之间的权值是两个点的叉积然后从第一个点到达第n个点总权值最小。

题解:因为凸包是求逆时针的时候面积包住所有点的面积最大,那么我们题目这样是顺时针,相反的就是面积最小,所以这题就是求顺时针的凸包,将中间的那些点按x从小到大,y从小到大,编号从小到大排序然后扫描法选取凸包即可,因为会有从点所以相同的点我们选取编号最小的点即可

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<stack>
#include<bitset>
using namespace std;
#define mes(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define dec(i,a,b) for(int i = b; i >= a; i--)
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,L,mid
#define rson rs,mid+1,R
#define lowbit(x) x&(-x)
typedef double db;
typedef long long int ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
const ll inf = 0x3f3f3f3f;
const int mx = 2e5+5;
const int mod = 1e9+7;
const int x_move[] = {1,-1,0,0,1,1,-1,-1};
const int y_move[] = {0,0,1,-1,1,-1,1,-1};
int n,m;
struct node{
	ll x,y;
	int id;
	bool operator<(const node &a)const{
		if(x!=a.x)	return x < a.x;
		if(y!=a.y) return y < a.y;
		return id < a.id;
	}
	bool operator!=(const node &a){
		return x!=a.x||y!=a.y;
	}
	friend node operator-(const node &a,const node &b){
		node c;
		c.x = a.x-b.x;
		c.y = a.y-b.y;
		c.id = a.id;
		return c;
	}
	ll operator*(node &a){
		return x*a.y-a.x*y;
	}
}a[mx],st[mx];
int top;
bool judge(node a,node b,node c){
	c = c-a;
	b = b-a;
	if(b*c>0)
		return true;
	else if(b*c==0&&c.id<b.id)
		return true;
	return false;
}
int main(){
	//freopen("test.in","r",stdin);
	//freopen("test.out","w",stdout);
	int t,ca = 1;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i = 1; i <= n; i++)
			scanf("%lld%lld",&a[i].x,&a[i].y),a[i].id = i;
		sort(a+2,a+n);
		top = 0;
		st[++top] = a[1];
		st[++top] = a[2];
		for(int i = 3; i <= n; i++)if(a[i]!=a[i-1]){
			while(top>=2&&judge(st[top-1],st[top],a[i]))
				top--;
			st[++top] = a[i];
		}
		for(int i = 1; i <= top; i++)
			printf("%d%c",st[i].id,i==top?'\n':' ');
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a1325136367/article/details/81297176