POJ 3348 :http://poj.org/problem?id=3348
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long LL;
const int N = 10005;
struct point {
double x,y;
point() {}
point(double _x,double _y):
x(_x),y(_y) {}
friend point operator - (const point &a,const point &b) {
return point(a.x-b.x,a.y-b.y);
}
friend double operator * (const point &a,const point &b) {
return a.x*b.y-a.y*b.x;
}
double dis() {
return x*x+y*y;
}
} p[N],ans[N];
int n,m;
bool cmp(point a,point b) { //极角排序另一种方法,精度高
double xx=p[1].x,yy=p[1].y;
point p0=point {xx,yy};
a=a-p0;
b=b-p0;
if(a*b!=0)
return a*b>0;
return a.x<b.x;
}
bool cmp1(point a,point b){//极角排序另一种方法,速度快
double xx=p[1].x,yy=p[1].y;
if(atan2(a.y-yy,a.x-xx)!=atan2(b.y-yy,b.x-xx))
return (atan2(a.y-yy,a.x-xx))<(atan2(b.y-yy,b.x-xx));
return a.x<b.x;
}
void graham() {
int id=1;
m=0;
for(int i=2; i<=n; i++)
if(p[i].x<p[id].x||(p[i].x==p[id].x&&p[i].y<p[id].y))
id=i;
if(id!=1)
swap(p[1],p[id]);
//寻找最左下的点
sort(p+2,p+n+1,cmp);
//极角排序
ans[++m]=p[1];
for(int i=2; i<=n; i++) {
//遍历每一个点,如果当前点形成凹多边形,即弹出
while(m>=2 && (ans[m]-ans[m-1])*(p[i]-ans[m])<=0) m--;
ans[++m]=p[i];
}
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;++i) {
scanf("%lf%lf",&p[i].x,&p[i].y);
}
if(n == 2 or n == 1) {
printf("0\n");
return 0;
}
graham();
double Ans=0;
for(int i=2;i<m;i++)
Ans+=(ans[i]-ans[1])*(ans[i+1]-ans[1]);
printf("%d\n",int(Ans/100));
return 0;
}
HDU 1392 :http://acm.hdu.edu.cn/showproblem.php?pid=1392
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long LL;
const int N = 10005;
struct point {
double x,y;
point() {}
point(double _x,double _y):
x(_x),y(_y) {}
friend point operator - (const point &a,const point &b) {
return point(a.x-b.x,a.y-b.y);
}
friend double operator * (const point &a,const point &b) {
return a.x*b.y-a.y*b.x;
}
double dis() {
return x*x+y*y;
}
} p[N],ans[N];
int n,m;
bool cmp(point a,point b) { //极角排序另一种方法,精度高
double xx=p[1].x,yy=p[1].y;
point p0=point {xx,yy};
a=a-p0;
b=b-p0;
if(a*b!=0)
return a*b>0;
return a.x<b.x;
}
bool cmp1(point a,point b){//极角排序另一种方法,速度快
double xx=p[1].x,yy=p[1].y;
if(atan2(a.y-yy,a.x-xx)!=atan2(b.y-yy,b.x-xx))
return (atan2(a.y-yy,a.x-xx))<(atan2(b.y-yy,b.x-xx));
return a.x<b.x;
}
void graham() {
int id=1;
m=0;
for(int i=2; i<=n; i++)
if(p[i].x<p[id].x||(p[i].x==p[id].x&&p[i].y<p[id].y))
id=i;
if(id!=1)
swap(p[1],p[id]);
//寻找最左下的点
sort(p+2,p+n+1,cmp);
//极角排序
ans[++m]=p[1];
for(int i=2; i<=n; i++) {
//遍历每一个点,如果当前点形成凹多边形,即弹出
while(m>=2 && (ans[m]-ans[m-1])*(p[i]-ans[m])<=0) m--;
ans[++m]=p[i];
}
}
double Dis(point a,point b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int main() {
while(~scanf("%d",&n) and n!=0) {
for(int i=1; i<=n; ++i) {
scanf("%lf%lf",&p[i].x,&p[i].y);
}
if(n == 2) {
printf("%.2lf\n",Dis(p[1],p[2]));
continue;
}
graham();
double Ans=0;
ans[m+1]=ans[1];//cout<<m<<endl;
for(int i=1; i<=m; ++i)
Ans+=Dis(ans[i],ans[i+1]);
printf("%.2lf\n",Ans);
}
return 0;
}
POJ 1228 :http://poj.org/problem?id=1228
这个题求的是一个稳定凸包,网上一堆人说要求共线凸包,就是所有在凸包边上的点都存在ans数组里面,我多次尝试无果
然后用他们的代码测试,发现他们的代码也无法完成,题中样例都无法过去,于是还是用了原来的板子求了纯净凸包,然后O(n²)过的
然而这些所谓共线凸包的代码,并不能通过所有点在一条直线上的样例
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long LL;
const int N = 1010;
struct point {
double x,y;
point() {}
point(double _x,double _y):
x(_x),y(_y) {}
friend point operator - (const point &a,const point &b) {
return point(a.x-b.x,a.y-b.y);
}
friend double operator * (const point &a,const point &b) {
return a.x*b.y-a.y*b.x;
}
double dis() {
return x*x+y*y;
}
} p[N],ans[N];
int n,m;
double dis(point a, point b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
bool cmp(point a,point b) { //极角排序另一种方法,精度高
double xx=p[1].x,yy=p[1].y;
point p0=point {xx,yy};
a=a-p0;
b=b-p0;
if(a*b!=0)
return a*b>0;
return a.x<b.x;
}
bool cmp1(point a,point b) { //极角排序另一种方法,速度快
double xx=p[1].x,yy=p[1].y;
if(atan2(a.y-yy,a.x-xx)!=atan2(b.y-yy,b.x-xx))
return (atan2(a.y-yy,a.x-xx))<(atan2(b.y-yy,b.x-xx));
return a.x<b.x;
}
void graham() {
int id=1;
m=0;
for(int i=2; i<=n; i++)
if(p[i].x<p[id].x||(p[i].x==p[id].x&&p[i].y<p[id].y))
id=i;
if(id!=1)
swap(p[1],p[id]);
//寻找最左下的点
sort(p+2,p+n+1,cmp);
//极角排序
ans[++m]=p[1];//cout<<p[1].x<<" "<<p[1].y<<endl;
for(int i=2; i<=n; i++) {//cout<<p[i].x<<" "<<p[i].y<<endl;
//遍历每一个点,如果当前点形成凹多边形,即弹出
while(m>=2 && (p[i]-ans[m])*(ans[m-1]-ans[m])<=0) m--;
ans[++m]=p[i];//cout<<m<<endl;
}
}
double multi(point p1, point p2, point p3) {
return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%lf%lf",&p[i].x,&p[i].y);
}
graham();
ans[m+1]=ans[1];
int flag=0;
for(int i=1; i<=m; i++) {
int sum=0;
for(int j=1; j<=n; j++) {
if(( (p[j]-ans[i+1]) * (ans[i]-ans[i+1]) )==0)
sum++;
}
if(sum<3) {
flag=1;
break;
}
}
if(flag==0 && m>=3)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
判断点是否在多边形内部:
bool onsegment(point pi,point pj,point Q) {
if((Q.x-pi.x)*(pj.y-pi.y)==(pj.x-pi.x)*(Q.y-pi.y)&&min(pi.x,pj.x)<=Q.x&&Q.x<=max(pi.x,pj.x)&&min(pi.y,pj.y)<=Q.y&&Q.y<=max(pi.y,pj.y)) {
return true;
} else {
return false;
}
}
bool insidepolygon(point pp) {
int counter=0;
double xinters;
point p1,p2;
p1=p[1];
for(int i=2; i<=n+1; i++) {
p2=p[i%(n+1)];
if(onsegment(p1,p2,pp)) {
return true;
}
if(pp.y>min(p1.y,p2.y)) {
if(pp.y<=max(p1.y,p2.y)) {
if(pp.x<=max(p1.x,p2.x)) {
if(p1.y!=p2.y) {
xinters=(pp.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
if(p1.x==p2.x||pp.x<=xinters) {
counter++;
}
}
}
}
}
p1=p2;
}
if(counter%2==0) {
return false;
}
return true;
}