HDU 4946 凸包 判重点 多校练习赛8 1002

56 篇文章 0 订阅
7 篇文章 0 订阅


题目意思很无聊, 你可以证明两点。

A、 速度最大的才能到最远点

B、 只有凸包边上的点才能到无穷远点。


然后就是一个无聊的凸包, 人站在一起并且速度相同的要排除掉。

。。被自己这个模板坑死了。  。。后来手动加上判是否在凸包上才过掉。。白浪费了3小时。。

#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <sstream>
#include <math.h>

#define mp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define pLL pair<long long ,long long>
#define pb(x) push_back(x)
#define rep(i,j,k) for(int i = j; i < k;i++)

#define MAX(x,a)  x=((x)<(a))?(a):(x);
#define MIN(x,a)  x=((x)>(a))?(a):(x);

using namespace std;

typedef int Type;
const int N = 1000;
const Type eps = 1e-8;
struct point
{
    Type x,y;
	int v;
	int ind;
	bool legal;
	point(){}
	point(Type _x,Type _y){ x=_x,y=_y;}
	friend bool operator < (const point &l, const point &r) {
        return l.y < r.y || (l.y == r.y && l.x < r.x);
    }
	void input(){
		scanf("%d %d %d",&x,&y,&v);
		legal = false; 
	}
}P[N],res[N],K[N];


//叉积
//  P1
//    \
// .p0 \
//      p2
//  这种情况。返回结果顺时针<0,逆时针>0
long long Multi(point p1, point p2, point p0) {
    return (long long)(p1.x - p0.x) * (p2.y - p0.y) - (long long)(p2.x - p0.x) * (p1.y - p0.y);
}
 
//逆时针顺序
//p数组是点集, res是最后的结果集 , 同一条线上的会被移除一些。但可以修改 <=来避免
int Graham(point p[], int n, point res[]) {
    int top = 1;
    sort(p, p + n);
    if (n == 0){
		return 0;
	}
    res[0] = p[0];
    if (n == 1) return 1;
    res[1] = p[1];
    if (n == 2) return 2;
    res[2] = p[2];
    for (int i = 2; i < n; i++) {
        while (top && (Multi(p[i], res[top], res[top - 1]) >= 0))   //这里更改是逆时针还是顺时针
            top--;
        res[++top] = p[i];
    }
    int len = top;
    res[++top] = p[n - 2];
    for (int i = n - 3; i >= 0; i--) {
		//只有当你需要求凸包上有多少个时,你才需要去掉 = . 
        while (top != len && (Multi(p[i], res[top], res[top - 1]) >= 0))  //这里更改是逆时针还是顺时针
            top--;
        res[++top] = p[i];
    }
	//需要注意的是 最后点为  0 1 2 3 0,top指向最后一个元素 ,top就是里面的元素的数目了。。
    return top; 
}
int maxv,fn;
int top;
bool vis[N];
char s[N];
// p1.x <= a.x && a.x <= p2.x && p1.y <= a.y && a.y <= p2.y
		// &&
bool inLine(point a,point p1,point p2){
	if( (p1.x <= a.x && a.x <= p2.x)
	||  (p2.x <= a.x && a.x <= p1.x))
	if( (p1.y <= a.y && a.y <= p2.y)
	||	p2.y <= a.y && a.y <= p1.y)
	if( 
	Multi(p1,p2,a) == 0
	) return true;
	return false;
}
bool Equal(point i,point j){
	if( i.x == j.x && i.y == j.y && i.v==j.v){
		return true;
	}
	return false;
}
int main(){
	int n;
	int tt = 0;
	while(scanf("%d",&n)!=EOF){
		if(n == 0) break;
		memset(vis,0,sizeof(vis));
		rep(i,0,n)P[i].input(),P[i].ind = i;
		fn = 0 , maxv = 0;
		rep(i,0,n){
			if(P[i].v > maxv){
				maxv = P[i].v;
			}
		}
		rep(i,0,n) if(P[i].v == maxv){
			K[fn++] = P[i];
		}
		top = Graham(K,fn,res);
		for(int i = 0;i < n;i++) s[i]='0'; s[n]='\0';
		for(int i = 0; i < top;i++) {
			vis[res[i].ind] = true,s[res[i].ind] = '1';
		}
		
		for(int j = 0;j < n;j++){
			if(P[j].v == maxv)
				for(int i = 0;i < top;i++)
				if(inLine(P[j],res[i],res[i+1])){
					s[j] = '1';
					break;
				}
		}
		
		for(int i = 0;i < n;i++)
			if(P[i].v == maxv)
				for(int j = 0;j < n;j++)
					if(i!=j)
						if(Equal(P[i],P[j])){
							s[P[i].ind] = '0';
							break;
						}
		rep(i,0,n)
			if(P[i].v < maxv)
				s[i] = '0';
		if(maxv == 0){
			rep(i,0,n) s[i] = '0';
		}
		printf("Case #%d: %s\n",++tt,s);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值