您的位置:首页 > 其它

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

2014-08-14 17:29 316 查看
题目意思很无聊, 你可以证明两点。

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
,res
,K
;

//叉积
// 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
;
char s
;
// 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
='\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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息