A - Wall
题意:
建立围墙将城堡围起来,要求围墙至少距离城堡L,拐角处用圆弧取代,求围墙的长度。
题解:
答案是凸包周长加上一个圆周长。
#include
#include
#include
#include
using namespace std;
const int MAXN=1010;
const double PI=acos(-1.0);
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
};
typedef Point Vector;
Point in[MAXN],out[MAXN];
Vector operator +(Vector A,Vector B)
{
return Vector(A.x+B.x,A.y+B.y);
}
Vector operator - (Vector A,Vector B)
{
return Vector(A.x-B.x,A.y-B.y);
}
bool operator <(const Point& a,const Point &b)
{
return a.x1&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
int k=m;
for(int i=n-2;i>=0;i--)
{
while(m>k&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
if(n>1) m--;
return m;
}
double length(Vector A)
{
return sqrt(A.x*A.x+A.y*A.y);
}
double perimeter(Point *p,int n)
{
double len=0;
for(int i=0;i
B - Scrambled Polygon
题意:
给出一个多边形的起点和n-1个乱序的坐标点,要求从起点逆序输出左边点
题解:
用叉积进行排序
#include
#include
#include
#include
using namespace std;
const int MAXN=500000;
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
};
Point s(0.0,0.0);
Point point[MAXN];
typedef Point Vector;
Vector operator -(Vector A,Vector B)
{
return Vector(A.x-B.x,A.y-B.y);
}
double cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
int cmp(Point a,Point b)
{
return cross(a-s,b-s)>0;
}
int main()
{
double x,y;
int cnt=0;
scanf("%lf%lf",&s.x,&s.y);
while(scanf("%lf%lf",&x,&y)!=EOF)
{
point[++cnt]=Point(x,y);
}
sort(point+1,point+1+cnt,cmp);
printf("(%.f,%.f)\n",s.x,s.y);
for(int i=1;i<=cnt;i++)
{
printf("(%.f,%.f)\n",point[i].x,point[i].y);
}
}
C - The Fortified Forest
待填坑!!!
待填坑!!!
待填坑!!!
E - Cows
题解:
求凸包面积再除以50
#include
#include
#include
#include
using namespace std;
const int MAXN=10010;
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
};
typedef Point Vector;
Point in[MAXN],out[MAXN];
bool operator <(const Point &a,const Point &b )
{
return a.x1&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
int k=m;
for(int i=n-2;i>=0;i--)
{
while(m>k&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
if(n>1) m--;
return m;
}
double polyArea(Point *p,int n)
{
double area=0.0;
for(int i=1;i
Separate Points
题意:
有黑白两种颜色的点,判断是否可以用一条直线划分成颜色一致的两部分(输入点无坐标相同的点,直线上不能有输入点)
题解:
分别求出黑点的凸包,再求出白点的凸包,如果两个凸包可以分离,那么可以用直线划分;
可以分离的充要条件是两个凸包的边界和内部没有公共部分(哪怕一个点也不行)
(一)任取一个黑点,判断是否在白凸包内部;如果是,则无解;否则,再取白点,判断是否在凸包的内部,如果是,则无解
(二)任取黑凸包的线段判断是否和白凸包的线段是否规范相交,如果是,则无解
以上两个条件都满足才可以划分点集
#include
#include
#include
#include
using namespace std;
const int MAXN=110;
const int INF=0x7fffffff;
const double EPS=1e-10;
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
};
Point white[MAXN],black[MAXN],wout[MAXN],bout[MAXN];
typedef Point Vector;
Vector operator -(Vector A,Vector B)
{
return Vector(A.x-B.x,A.y-B.y);
}
bool operator <(const Point &a,const Point &b)
{
return a.x1&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
int k=m;
for(int i=n-2;i>=0;i--)
{
while(m>k&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
if(n>1) m--;
return m;
}
int dcmp(double val)
{
if(abs(val)0) return 1;
else return -1;
}
bool isPointOnSegment(Point p,Point a,Point b)//点在线段上(不包括端点)
{
return cross(a-p,b-p)==0&&dot(a-p,b-p)<0;
}
bool segmentInterect(Point a1,Point a2,Point b1,Point b2)//规范相交
{
int c1=cross(a2-a1,b1-a1),c2=cross(a2-a1,b2-a1);
int c3=cross(b2-b1,a1-b1),c4=cross(b2-b1,a2-b1);
return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
}
int isPointInPolygon(Point *ch,int n,Point p)//是否在多边形内部
{
int wn=0;
for(int i=0;i0&&d1<=0&&d2>0) wn++;
if(k<0&&d2<=0&&d1>0) wn--;
}
if(wn) return 1;
else return 0;
}
int main()
{
int n,m,bct,wct;
while(scanf("%d%d",&n,&m)!=EOF,n+m)
{
for(int i=0;i
B - Shape of HDU
题意:
给定多边形的逆序节点,判断一个多边形是不是凸多边形
题解:
可以用相邻两边的旋转角来判断,逆时针取点,若存在点p1, p2, p3,矢边p1p2, 到p2p3,为顺时针旋转则此多边形为凹多边形,可以用叉积判断时针方向
#include
#include
#include
#include
using namespace std;
const int MAXN=50000;
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
};
Point point[MAXN];
typedef Point Vector;
Vector operator +(Vector A,Vector B)
{
return Vector(A.x+B.x,A.y+B.y);
}
Vector operator - (Vector A,Vector B)
{
return Vector(A.x-B.x,A.y-B.y);
}
double cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF,n)
{
for(int i=0;i
C - Surround the Trees
题意:
求凸包周长
题解:
这里比较坑的地方有,1个点的时候输出0,两个点的时候,凸包求出来是有两条边的,但是只需输出两点距离即可
#include
#include
#include
#include
using namespace std;
const int MAXN=110;
struct Point
{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
};
Point in[MAXN],out[MAXN];
typedef Point Vector;
Vector operator +(Vector A,Vector B)
{
return Vector(A.x+B.x,A.y+B.y);
}
Vector operator -(Vector A,Vector B)
{
return Vector(A.x-B.x,A.y-B.y);
}
double cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
bool operator <(const Point &a,const Point &b)
{
return a.x1&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
int k=m;
for(int i=n-2;i>=0;i--)
{
while(m>k&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
ch[m++]=p[i];
}
if(n>1) m--;
return m;
}
double length(Vector A)
{
return sqrt(A.x*A.x+A.y*A.y);
}
double perimeter(Point *p,int n)
{
double len=0;
for(int i=0;i