凸包总结
这几天终于开始学了计算几何了,整个人都萌萌哒~~~
首先当然是凸包啦~~~
凸包的算法还不算难啦,就是找到一定在凸包上的点,然后就按这个点为o点按极角排序,然后就弄个栈维护啦~~~
然后就做几道题啦~~~
poj 1113 WALL
这道题直接求出凸包的长度加个圆就行了
第一次打凸包弄到死,结果是while写成if了= =
CODE:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define fi first
#define se second
#define sqr(x) ((x)*(x))
typedef pair<int,int> ii;
#define pi acos(-1.0)
ii dec(ii x,ii y){
return ii(x.fi-y.fi,x.se-y.se);
}
int cross(ii x,ii y){
return (x.fi*y.se-x.se*y.fi);
}
int dist(ii x){
return sqr(x.fi)+sqr(x.se);
}
#define maxn 1010
ii a[maxn];
bool cmp(ii x,ii y){
int m=cross(dec(a[1],x),dec(a[1],y));
if (m!=0) return m>0;
return (dist(dec(a[1],x))<dist(dec(a[1],y)));
}
int n,l,q[maxn],r;
double ans;
int main(){
scanf("%d%d",&n,&r);
int x=1;
for (int i=1;i<=n;i++) {
scanf("%d%d",&a[i].fi,&a[i].se);
if (a[x].second>a[i].second||(a[x].second>a[i].second&&a[x].fi>a[i].fi)) x=i;
}
swap(a[1],a[x]);
sort(a+2,a+1+n,cmp);
q[1]=1;q[2]=2;l=2;
for (int i=3;i<=n;i++) {
while (l>1&&cross(dec(a[q[l-1]],a[q[l]]),dec(a[q[l]],a[i]))<=0) l--;
q[++l]=i;
}
q[l+1]=1;
for (int i=1;i<=l;i++) {
ans+=sqrt(dist(dec(a[q[i]],a[q[i+1]]) ) );
}
ans+=2.0*pi*(double)r;
printf("%.0f",ans);
return 0;
}
poj 1228 Grandpa's Estate
奇怪的题意,直接把凸包求出来然后判断每条边是否有3个点就行了
1A了真开心
CODE:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef pair<int,int> ii;
#define fi first
#define se second
ii dec(ii x,ii y){
return ii(x.fi-y.fi,x.se-y.se);
}
int cross(ii x,ii y){
return x.fi*y.se-x.se*y.fi;
}
#define sqr(x) ((x)*(x))
int dist(ii x){
return sqr(x.fi)+sqr(x.se);
}
ii a[1010];
bool cmp(ii x,ii y){
int m=cross(dec(a[1],x),dec(a[1],y));
if (m==0) return dist(dec(a[1],x))<dist(dec(a[1],y));
return m>0;
}
bool jiao(ii x,ii y,ii z){
int x1=min(x.fi,y.fi),x2=max(x.fi,y.fi);
int y1=min(x.se,y.se),y2=max(x.se,y.se);
if (z.fi<x1||z.fi>x2||z.se<y1||z.se>y2) return 0;
return cross(dec(x,z),dec(x,y))==0;
}
int n;
int init(){
scanf("%d",&n);
int root=1;
for (int i=1;i<=n;i++) {
scanf("%d %d",&a[i].fi,&a[i].se);
root=a[i]<a[root]?i:root;
}
swap(a[1],a[root]);
}
int q[1010];
int work(){
sort(a+2,a+1+n,cmp) ;
q[1]=1;q[2]=2;int l=2;
for (int i=3;i<=n;i++){
while (l>1&&cross(dec(a[q[l-1]],a[q[l]]),dec(a[q[l]],a[i]))<=0) l--;
q[++l]=i;
}
q[l+1]=1;bool flag=1;
for (int i=1;i<=l;i++) {
int cnt=0;
for (int j=1;j<=n;j++)
if (jiao(a[q[i]],a[q[i+1]],a[j])) cnt++;
if (cnt<3||cnt==n) flag=0;
}
printf("%s\n",flag?"YES":"NO");
return 0;
}
int main(){
int T;
scanf("%d",&T);
while (T--) {
init();
work();
}
return 0;
}
还有一道杂题
poj 2007 Scrambled Polygon
直接按极角排然后输出就行了
CODE:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define fi first
#define se second
#define maxn 100
typedef pair<int,int> ii;
ii a[maxn];
int n;
ii dec(ii x,ii y){
return ii(x.fi-y.fi,x.se-y.se);
}
int cross(ii x,ii y){
return x.fi*y.se-x.se*y.fi;
}
bool cmp(ii x,ii y){
return cross(dec(a[1],x),dec(a[1],y))>0;
}
int main(){
n=1;
while (scanf("%d%d",&a[n].fi,&a[n].se)!=EOF) n++;
n--;
sort(a+2,a+1+n,cmp);
for (int i=1;i<=n;i++) printf("(%d,%d)\n",a[i].fi,a[i].se);
return 0;
}
好了接下来就是半平面交了,加油!!