hdu 4946 Area of Mushroom (凸包,去重点,水平排序,留共线点)
题意:
在二维平面上,给定n个人
每个人的坐标和移动速度v
若对于某个点,只有 x 能最先到达(即没有人能比x先到这个点或者同时到这个点)
则这个点称作被x占有,若有人能占有无穷大的面积 则输出1 ,否则输出0
思路:
1、把所有点按速度排个序,然后把不是最大速度的点去掉
剩下的点才有可能是占有无穷大的面积
2、给速度最大的点做个凸包,则只有在凸包上的点才有可能占有无穷大
若一个位置有多个人,则这几个人都是不能占有无穷大的。
凸包上边里共线的点是要保留的。
#易错点:
1.凸包边上要保留共线的点,最好采用水平排序(构造凸包前)
2.对于去重点,必须在构造完凸包之后。
WA:构造凸包之前去重点(构造凸包的点不包括有重复的点)
#include<stdio.h> #include<algorithm> #include<fstream> #include<string.h> #include<iostream> using namespace std; const int MAX=550; struct point { int x; int y; int v; int i; }p[MAX],Ini[MAX],res[MAX]; int ans[MAX]; bool cmp(point A,point B) { if(A.y==B.y)return A.x<B.x; return A.y<B.y; } bool cmp1(point A,point B) { if(A.v>B.v)return true; if(A.v==B.v) { if(A.x<B.x)return true; if(A.x==B.x&&A.y<B.y)return true; } return false; } int cross(point A,point B,point C) { return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y); } int Graham(point *p,int n) { //if (n<3)return n; sort(p,p+n,cmp); int i; int top=0; for(i=0;i<n;i++) { while(top>=2&&cross(res[top-2],res[top-1],p[i])<0) top--; res[top++]=p[i]; } int t=top+1; for(i=n-2;i>=0;i--) { while(top>=t&&cross(res[top-2],res[top-1],p[i])<0) top--; res[top++]=p[i]; } /*for(i=0;i<top;i++) printf("%d %d\n",res[i].x,res[i].y);*/ return top; } int main() { int n; int i,j; //ifstream cin("A.txt"); int __case=0; while(cin>>n&&n) { for(i=0;i<n;i++) { cin>>Ini[i].x>>Ini[i].y>>Ini[i].v; Ini[i].i=i; } sort(Ini,Ini+n,cmp1); //cout<<Ini[i-1].x<<Ini[i-1].y; int tmp=0; for(i=0;i<n;i++) { if(Ini[0].v==Ini[i].v)tmp++; else break; } point po; for(i=0,j=0;i<tmp;) { po=Ini[i]; if(i<tmp-1&&Ini[i+1].x==Ini[i].x&&Ini[i+1].y==Ini[i].y) { while(i<tmp-1&&Ini[i+1].x==Ini[i].x&&Ini[i+1].y==Ini[i].y) i++; } else { p[j++]=po; } i++; } printf("Case #%d: ",++__case); int m=Graham(p,j); memset(ans,0,sizeof(ans)); for(i=0;i<m;i++) { //printf("%d %d %d",res[i].x,res[i].y,res[i].v); if(res[i].v>0) { ans[res[i].i]=1; } } for(i=0;i<n;i++) printf("%d",ans[i]); printf("\n"); } return 0; }
WA:构造凸包之后去重点
#include<stdio.h> #include<algorithm> #include<fstream> #include<string.h> #include<iostream> using namespace std; const int MAX=550; struct point { int x; int y; int v; int i; int tmp; } Ini[MAX],res[MAX]; bool flag[MAX]; int ans[MAX]; bool cmp(point A,point B) { if(A.y==B.y)return A.x<B.x; return A.y<B.y; } bool cmp1(point A,point B) { if(A.v>B.v)return true; return false; } int cross(point A,point B,point C) { return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y); } int Graham(point *p,int n) { //if (n<3)return n; sort(p,p+n,cmp); memset(flag,false,sizeof(flag)); int i; int top=0; for(i=0; i<n; i++) { while(top>=2&&cross(res[top-2],res[top-1],p[i])<0) top--; res[top++]=p[i]; res[top-1].tmp=i; } for(i=0;i<top;i++) flag[res[i].tmp]=true; int t=top+1; for(i=n-2; i>=0; i--) //i>=0 { while(top>=t&&cross(res[top-2],res[top-1],p[i])<0) top--; if(!flag[i])res[top++]=p[i]; //if(i==0)top--; } /*for(i=0; i<top; i++) printf("$%d %d\n",res[i].x,res[i].y);*/ return top; } int main() { int n; int i,j; //ifstream cin("A.txt"); int __case=0; while(cin>>n&&n) { for(i=0; i<n; i++) { cin>>Ini[i].x>>Ini[i].y>>Ini[i].v; Ini[i].i=i; } sort(Ini,Ini+n,cmp1); //cout<<Ini[i-1].x<<Ini[i-1].y; int tmp=0; for(i=0; i<n; i++) { if(Ini[0].v>0&&Ini[0].v==Ini[i].v)tmp++; else break; } int m=Graham(Ini,tmp); memset(ans,0,sizeof(ans)); printf("Case #%d: ",++__case); point po; for(i=0; i<m; i++) { po=res[i]; //printf("#%d %d %d\n",res[i].x,res[i].y,res[i].i); if(i<m-1&&res[i+1].x==po.x&&res[i+1].y==po.y) { while(i<m-1&&res[i+1].x==po.x&&res[i+1].y==po.y) i++; } else ans[po.i]=1; } for(i=0; i<n; i++) printf("%d",ans[i]); printf("\n"); } return 0; }
数据:
9 0 0 1 0 0 1 0 10 1 0 10 1 10 0 1 10 0 1 10 10 1 10 10 1 5 5 1
构造凸包之前去掉重点,保留相同点中的一个。
AC:
#include<stdio.h> #include<algorithm> #include<fstream> #include<string.h> #include<iostream> using namespace std; const int MAX=550; struct point { int x; int y; int v; int i; int tmp; } Ini[MAX],res[MAX],p[MAX]; bool flag[MAX]; int ans[MAX]; bool cmp(point A,point B) { if(A.y==B.y)return A.x<B.x; return A.y<B.y; } bool cmp1(point A,point B) { if(A.v>B.v)return true; if(A.v==B.v) { if(A.x<B.x)return true; if(A.x==B.x&&A.y<B.y)return true; } return false; } int cross(point A,point B,point C) { return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y); } int Graham(point *p,int n) { //if (n<3)return n; sort(p,p+n,cmp); memset(flag,false,sizeof(flag)); int i; int top=0; for(i=0; i<n; i++) { while(top>=2&&cross(res[top-2],res[top-1],p[i])<0) { top--; } res[top++]=p[i]; res[top-1].tmp=i; } for(i=0;i<top;i++) flag[res[i].tmp]=true; int t=top+1; for(i=n-2; i>=0; i--) //i>=0 { while(top>=t&&cross(res[top-2],res[top-1],p[i])<0) top--; if(!flag[i])res[top++]=p[i]; //if(i==0)top--; } /*for(i=0; i<top; i++) printf("$%d %d\n",res[i].x,res[i].y);*/ return top; } int main() { int n; int i,j; //ifstream cin("A.txt"); int __case=0; while(cin>>n&&n) { for(i=0; i<n; i++) { cin>>Ini[i].x>>Ini[i].y>>Ini[i].v; Ini[i].i=i; } sort(Ini,Ini+n,cmp1); //cout<<Ini[i-1].x<<Ini[i-1].y; int tmp=0; for(i=0; i<n; i++) { if(Ini[0].v>0&&Ini[0].v==Ini[i].v)tmp++; else break; } memset(ans,0,sizeof(ans)); point po; for(i=0,j=0;i<tmp;i++) { po=Ini[i]; //flag=1; if(i<tmp-1&&Ini[i+1].x==po.x&&Ini[i+1].y==po.y) { //flag=0; while(i<tmp-1&&Ini[i+1].x==po.x&&Ini[i+1].y==po.y) { ans[Ini[i].i]=-1; i++; } ans[Ini[i].i]=-1; } p[j++]=po; } int m=Graham(p,j); printf("Case #%d: ",++__case); for(i=0; i<m; i++) { if(!ans[res[i].i])ans[res[i].i]=1; } for(i=0; i<n; i++) { if(ans[i]==1)printf("1"); else printf("0"); } printf("\n"); } return 0; }