这个专题除了最后两题其他题目都是几个月前写的了,所以就贴一下代码好了,就最后两题简单地说了一下思路
目录
- A - TOYS (POJ - 2318)
- B - Toy Storage (POJ - 2398)
- C - Segments (POJ - 3304)
- D - Intersecting Lines (POJ 1269)
- E - The Doors (POJ - 1556)
- F - Pick-up sticks (POJ - 2653)
- G - Treasure Hunt (POJ - 1066)
- H - Intersection (POJ - 1410)
- I - Space Ant (POJ - 1696)
- J - Kadj Squares (POJ - 3347)
- K - An Easy Problem?! (POJ - 2826)
- L - Pipe (POJ - 1039)
- M - Geometric Shapes (POJ - 3449)
- N - A Round Peg in a Ground Hole (POJ - 1548)
A - TOYS (POJ - 2318)
AC Code:
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 5010;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否相交
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交
// return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0; 存在端点重合
}
int n, m, X1, X2, Y1, Y2, sum[maxn];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
while(cin>>n){
if(n == 0) break;
cin>>m>>X1>>Y1>>X2>>Y2;
L[0].p1.x = X1, L[0].p1.y = Y1;
L[0].p2.x = X1, L[0].p2.y = Y1 - 1;
for(int i = 1, u, l; i <= n; i++){
cin>>u>>l;
L[i].p1.x = u, L[i].p1.y = Y1;
L[i].p2.x = l, L[i].p2.y = Y2;
}
L[n + 1].p1.x = X2, L[n + 1].p1.y = Y2;
L[n + 1].p2.x = X2, L[n + 1].p2.y = Y2 - 1;
// for(int i = 0; i <= n + 1; i++) cout<<L[i].p1.x<<" "<<L[i].p1.y<<" "<<L[i].p2.x<<" "<<L[i].p2.y<<endl;
memset(sum, 0, sizeof(sum));
for(int i = 1, x, y; i <= m ; i++){
cin>>x>>y;
P[1].x = x, P[1].y = y;
// cout<<P[1].x<<" "<<P[1].y<<endl;
// for(int j = 0; j <= n; j++){
// if(Point_line_relation(P[1], L[j]) * Point_line_relation(P[1], L[j + 1]) == 2){
// sum[j]++;
// break;
// }
// }
int l = 0, r = n, mid = (l + r)/2;
while(r - l >= 0){
mid = (l + r)/2;
if(Point_line_relation(P[1], L[mid]) * Point_line_relation(P[1], L[mid + 1]) == 4) r = mid - 1;
else l = mid + 1;
}
sum[r]++;
}
for(int i = 0; i <= n; i++){
cout<<i<<": "<<sum[i]<<endl;
}
cout<<endl;
}
return 0;
}
B - Toy Storage (POJ - 2398)
AC Code:
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 5010;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否相交
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交
// return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0; 存在端点重合
}
int n, m, X1, X2, Y1, Y2, sum[maxn], ans[maxn];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
while(cin>>n){
if(n == 0) break;
cin>>m>>X1>>Y1>>X2>>Y2;
L[0].p1.x = X1, L[0].p1.y = Y1;
L[0].p2.x = X1, L[0].p2.y = Y1 - 1;
for(int i = 1, u, l; i <= n; i++){
cin>>u>>l;
L[i].p1.x = u, L[i].p1.y = Y1;
L[i].p2.x = l, L[i].p2.y = Y2;
}
L[n + 1].p1.x = X2, L[n + 1].p1.y = Y2;
L[n + 1].p2.x = X2, L[n + 1].p2.y = Y2 - 1;
sort(L,L + n + 2, cmp);
// for(int i = 0; i <= n + 1; i++) cout<<L[i].p1.x<<" "<<L[i].p1.y<<" "<<L[i].p2.x<<" "<<L[i].p2.y<<endl;
memset(sum, 0, sizeof(sum));
memset(ans, 0, sizeof(ans));
for(int i = 1, x, y; i <= m ; i++){
cin>>x>>y;
P[1].x = x, P[1].y = y;
// cout<<P[1].x<<" "<<P[1].y<<endl;
// for(int j = 0; j <= n; j++){
// if(Point_line_relation(P[1], L[j]) * Point_line_relation(P[1], L[j + 1]) == 2){
// sum[j]++;
// break;
// }
// }
int l = 0, r = n, mid = (l + r)/2;
while(r - l >= 0){
mid = (l + r)/2;
if(Point_line_relation(P[1], L[mid]) * Point_line_relation(P[1], L[mid + 1]) == 4) r = mid - 1;
else l = mid + 1;
}
sum[r]++;
}
for(int i = 0; i <= n; i++){
if(sum[i]) ans[sum[i]]++;
}
cout<<"Box"<<endl;
for(int i = 1; i <= m; i++){
if(ans[i]) cout<<i<<": "<<ans[i]<<endl;
}
}
return 0;
}
C - Segments (POJ - 3304)
AC Code:
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 5010;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否相交
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交
// return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0; 存在端点重合
}
int t, n, f;
bool judge(Line v){
for(int k = 1; k < 2 * n ; k = k + 2){
if(Point_line_relation(P[k], v) * Point_line_relation(P[k + 1],v) == 1 || Point_line_relation(P[k],v) * Point_line_relation(P[k + 1], v) == 4) return false;
}
return true;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>t;
while(t--){
cin>>n;
for(int i = 1; i <= 2 * n ; i ++){
cin>>P[i].x>>P[i].y;
}
f = 0;
for(int i = 1; i < 2 * n; i++){
for(int j = i + 1 ; j <= 2 * n; j++){
L[1].p1.x = P[i].x;
L[1].p1.y = P[i].y;
L[1].p2.x = P[j].x;
L[1].p2.y = P[j].y;
if(sgn(Dist(L[1].p1, L[1].p2)) == 0) continue;
if(judge(L[1])) f = 1;
if(f) break;
}
if(f) break;
}
if(f) puts("Yes!");
else puts("No!");
}
return 0;
}
D - Intersecting Lines (POJ 1269)
AC Code:
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 5010;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否相交
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交
// return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0; 存在端点重合
}
int n;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
cout<<"INTERSECTING LINES OUTPUT"<<endl;
while(n--){
cin>>L[1].p1.x>>L[1].p1.y>>L[1].p2.x>>L[1].p2.y;
cin>>L[2].p1.x>>L[2].p1.y>>L[2].p2.x>>L[2].p2.y;
if(Line_relation(L[1], L[2]) == 1) cout<<"LINE"<<endl;
else if(Line_relation(L[1], L[2]) == 0) cout<<"NONE"<<endl;
else{
P[1] = Cross_point(L[1].p1, L[1].p2, L[2].p1, L[2].p2);
cout<<"POINT ";
cout<<fixed<<setprecision(2)<<P[1].x<<" "<<P[1].y<<endl;
}
}
cout<<"END OF OUTPUT"<<endl;
return 0;
}
E - The Doors (POJ - 1556)
AC Code:
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 110;
const int mod = 1e9 + 7;
int sgn(double x){
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector;
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}
bool Cross_segment(Point a, Point b, Point c, Point d){
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0;
}
int n;
double x, y;
bool judge(Line v){
for(int k = 1; k <= 6 * n; k+=2){
if(Cross_segment(L[1].p1, L[1].p2, P[k], P[k + 1]) == 1) return false;
}
return true;
}
double d[maxn];
int vis[maxn];
struct node{
int to;
double w;
node(int to_,double w_){
to = to_,w = w_;
}
};
vector<node>v[maxn];
void Dij(){
d[0] = 0;
while(1){
double min1=999999.0 ;
int z = -1;
for(int i = 0;i < 6 * n + 1; i++){
if(d[i] < min1 && !vis[i]){
min1 = d[i];
z = i;
}
}
if(z == -1) break;
vis[z] = 1;
for(int i = 0;i < v[z].size(); i++){
int vv = v[z][i].to;
double dis = v[z][i].w;
if(d[vv] > dis + d[z]) d[vv] = dis + d[z];
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
while(cin>>n){
if(n == -1) break;
for(int i = 0;i <= 6 * n + 1;i++){
v[i].clear();
vis[i]=0;
d[i]=99999.0;
}
P[0].x = 0;
P[0].y = 5;
for(int i = 1; i <= n; i++){
cin>>x;
P[(i - 1) * 6 + 1].x = x;
P[(i - 1) * 6 + 1].y = 0;
for(int j = 2; j <= 5; j++){
cin>>y;
P[(i - 1) * 6 + j].x = x;
P[(i - 1) * 6 + j].y = y;
}
P[(i - 1) * 6 + 6].x = x;
P[(i - 1) * 6 + 6].y = 10;
}
P[6 * n + 1].x = 10;
P[6 * n + 1].y = 5; //true
for(int i = 0; i < 6 * n + 1; i++){
if((i % 6 == 1 || i % 6 == 0) && i != 0) continue;
for(int j = i + 1; j <= 6 * n + 1; j++){
if((j % 6 == 1 || j % 6 == 0) && j != 6 * n + 1) continue;
L[1].p1.x = P[i].x;
L[1].p1.y = P[i].y;
L[1].p2.x = P[j].x;
L[1].p2.y = P[j].y;
if(judge(L[1])){
double dist = Dist(P[i] ,P[j]);
v[i].push_back(node(j, dist));
}
}
}
Dij();
cout<<fixed<<setprecision(2)<<d[6 * n + 1]<<endl;
}
return 0;
}
F - Pick-up sticks (POJ - 2653)
AC Code:
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 100010;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否相交
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交,端点重合不相交
// return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0; //端点重合算相交
}
int n, a[maxn];
double X1, X2, Y1, Y2;
bool judge(Line v1, Line v2){
if(Cross_segment(v1.p1, v1.p2, v2.p1, v2.p2)) return false;
return true;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
while(cin>>n){
if(n == 0) break;
for(int i = 1; i <= n; i++){
cin>>X1>>Y1>>X2>>Y2;
L[i].p1.x = X1;
L[i].p1.y = Y1;
L[i].p2.x = X2;
L[i].p2.y = Y2;
}
memset(a, 0, sizeof(a));
int cnt = 0;
for(int i = 1; i < n; i++){
int f = 1;
for(int j = i + 1; j <= n; j++){
if(!judge(L[i], L[j])){
f = 0;
break;
}
}
if(f){
cnt++;
a[cnt] = i;
}
}
cnt++;
a[cnt] = n;
cout<<"Top sticks:";
for(int i = 1; i < cnt; i++) cout<<" "<<a[i]<<",";
cout<<" "<<a[cnt]<<"."<<endl;
}
return 0;
}
G - Treasure Hunt (POJ - 1066)
AC Code:
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 110;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否相交
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交,端点重合不相交
// return sgn(c1) * sgn(c2) <= 0 && sgn(d1) * sgn(d2) <= 0; //端点重合算相交
}
int n;
double X1, X2, Y1, Y2;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i = 1; i <= 2 * n; i = i + 2){
cin>>X1>>Y1>>X2>>Y2;
P[i].x = X1;
P[i].y = Y1;
P[i + 1].x = X2;
P[i + 1].y = Y2;
}
cin>>P[0].x>>P[0].y;
int minn = inf, ans = 0;
for(int i = 1; i <= 2 * n; i++){
ans = 0;
for(int j = 1; j <= 2 * n; j = j + 2){
if(Cross_segment(P[0], P[i], P[j], P[j + 1])) ans++;
}
minn = min(ans, minn);
}
if(n == 0) minn = 0;
cout<<"Number of doors = "<<minn + 1<<endl;
return 0;
}
H - Intersection (POJ - 1410)
AC Code:
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 110;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否规范相交 即如果一条线段的一个端点恰在另一条线段上则不视为相交;如果两条线段部分重合,也不视为相交。
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交,端点重合不相交
}
bool Cross_segment1(Point a, Point b, Point c, Point d){ //两线段是否非规范相交
return
max(a.x, b.x) >= min(c.x, d.x)&&
max(c.x, d.x) >= min(a.x, b.x)&&
max(a.y, b.y) >= min(c.y, d.y)&&
max(c.y, d.y) >= min(a.y, b.y)&&
sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
}
int n;
double X1, X2, Y1, Y2, topx, topy, botx, boty, X3, X4, Y3, Y4;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
while(n--){
cin>>X1>>Y1>>X2>>Y2>>X3>>Y3>>X4>>Y4;
topx = max(X3, X4);
botx = min(X3, X4);
topy = max(Y3, Y4);
boty = min(Y3, Y4);
P[1].x = X1;
P[1].y = Y1;
P[2].x = X2;
P[2].y = Y2;
P[3].x = topx;
P[3].y = topy;
P[4].x = topx;
P[4].y = boty;
P[5].x = botx;
P[5].y = boty;
P[6].x = botx;
P[6].y = topy;
int f = 0;
if(Cross_segment1(P[1], P[2], P[3], P[4])) f = 1;
if(Cross_segment1(P[1], P[2], P[3], P[6])) f = 1;
if(Cross_segment1(P[1], P[2], P[5], P[4])) f = 1;
if(Cross_segment1(P[1], P[2], P[5], P[6])) f = 1;
if(max(X1, X2) < topx && max(Y1, Y2) < topy && min(X1, X2) > botx && min(Y1, Y2) > boty) f = 1;
if(f) cout<<"T"<<endl;
else cout<<"F"<<endl;
}
return 0;
}
I - Space Ant (POJ - 1696)
AC Code:
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 60;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否规范相交 即如果一条线段的一个端点恰在另一条线段上则不视为相交;如果两条线段部分重合,也不视为相交。
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交,端点重合不相交
}
bool Cross_segment1(Point a, Point b, Point c, Point d){ //两线段是否非规范相交
return
max(a.x, b.x) >= min(c.x, d.x)&&
max(c.x, d.x) >= min(a.x, b.x)&&
max(a.y, b.y) >= min(c.y, d.y)&&
max(c.y, d.y) >= min(a.y, b.y)&&
sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
sgn(Cross(c - b, a - b)) * sgn(Cross(d - b, a - b)) <= 0&&
sgn(Cross(a - d, c - d)) * sgn(Cross(b - d, c - d)) <= 0;
}
double Helen(double a, double b, double c){
double p = (a + b + c)/2;
return sqrt(p * (p - a) * (p - b) * (p - c));
}
int t, n, num, vis[maxn];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>t;
while(t--){
cin>>n;
memset(vis, 0, sizeof(vis));
double boty = inf;
double minn = inf, angle = 0;
int pre= 0, first = 0;
for(int i = 1; i <= n; i++){
cin>>num>>P[i].x>>P[i].y;
if(P[i].y < boty){
boty = P[i].y;
pre = i;
}
}
P[0] = {0, boty};
cout<<n<<" "<<pre;
vis[pre] = 1;
int N = n;
n--;
int last = 0;
while(n--){
minn = inf;
for(int i = 1; i <= N; i++){
if(vis[i]) continue;
angle = Angle(P[pre] - P[first], P[i] - P[pre]);
if(angle - minn< eps){
minn = angle;
last = i;
}
}
vis[last] = 1;
first = pre;
pre = last;
cout<<" "<<pre;
}
cout<<endl;
}
return 0;
}
J - Kadj Squares (POJ - 3347)
AC Code:
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-10
#define endl "\n"
const int maxn = 60;
const int mod = 1e9 + 7;
const double pi = acos(-1.0);
int moven2[10][5] = {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}};
int moven1[10][5] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int n, a[maxn], p[maxn], q[maxn];
vector<int>v;
int main() {
// ios::sync_with_stdio(false);
// cin.tie(0);cout.tie(0);
while(~scanf("%d", &n)){
if(n == 0) break;
v.clear();
memset(p, 0, sizeof(p));
for(int i = 1;i <= n; i++)
scanf("%d",&a[i]);
for(int i = 1;i <= n; i++){
for(int j = 1; j <= i - 1; j++)
p[i] = max(p[i],q[j] - abs(a[j] - a[i]));
q[i] = p[i] + 2 * a[i];
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= i - 1; j++){
if(q[j] > p[i]){
if(a[j] < a[i]) q[j] = p[i];
else if(a[j] > a[i]) p[i] = q[j];
}
}
}
for(int i = 1; i <= n; i++){
if(p[i] < q[i]) v.push_back(i);
}
for(int i = 0; i < v.size(); i++){
printf("%d%c",v[i], i == v.size() - 1? '\n' : ' ');
}
}
return 0;
}
K - An Easy Problem?! (POJ - 2826)
AC Code:
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 1000010;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
bool operator < (const Point &b)const{
if(x == b.x) return y < b.y;
return x < b.x;
}
}P[maxn];
Point ch[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否规范相交 即如果一条线段的一个端点恰在另一条线段上则不视为相交;如果两条线段部分重合,也不视为相交。
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交,端点重合不相交
}
bool Cross_segment1(Point a, Point b, Point c, Point d){ //两线段是否非规范相交
return
max(a.x, b.x) >= min(c.x, d.x)&&
max(c.x, d.x) >= min(a.x, b.x)&&
max(a.y, b.y) >= min(c.y, d.y)&&
max(c.y, d.y) >= min(a.y, b.y)&&
sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
sgn(Cross(c - b, a - b)) * sgn(Cross(d - b, a - b)) <= 0&&
sgn(Cross(a - d, c - d)) * sgn(Cross(b - d, c - d)) <= 0;
}
double Helen(double a, double b, double c){ //海伦公式
double p = (a + b + c)/2;
return sqrt(p * (p - a) * (p - b) * (p - c));
}
int Point_in_polygon(Point pt, Point *p, int n){ //判断点和多边形的位置关系
for(int i = 0; i < n; i++){
if(p[i] == pt) return 3; //点在多边形的顶点上
}
for(int i = 0; i < n; i++){
Line v = Line(p[i], p[(i + 1) % n]);
if(Point_on_seg(pt, v)) return 2; //点在多边形边上
}
int num = 0;
for(int i = 0; i < n; i++){
int j = (i + 1) % n;
int c = sgn(Cross(pt - p[j], p[i] - p[j]));
int u = sgn(p[i].y - pt.y);
int v = sgn(p[j].y - pt.y);
if(c > 0 && u < 0 && v >= 0) num++;
if(c < 0 && u >= 0 && v < 0) num--;
}
return num != 0; //1点在内部; 0点在外部
}
double Polygon_area(Point *p, int n){ //求多边形面积
double area = 0;
for (int i = 0; i < n; ++i)
area += Cross(p[i], p[i + 1]);
return area / 2;
}
Point Polygon_center(Point *p, int n){ //求多边形的重心
Point ans(0, 0);
if(Polygon_area(p, n) == 0) return ans;
for(int i = 0; i < n; i++)
ans = ans + (p[i] + p[(i + 1) % n]) * Cross(p[i], p[(i + 1) % n]);
return ans / Polygon_area(p, n) / 6;
}
int Andrew(int n){ //求凸包
sort(P, P + n);
int len = 0;
for(int i = 0; i < n; i++){
while(len > 1 && sgn(Cross(ch[len] - ch[len - 1], P[i] - ch[len - 1])) == -1) len--;
ch[++len] = P[i];
}
int k = len;
for(int i = n - 2; i >= 0; i--){
while(len > k && sgn(Cross(ch[len] - ch[len - 1], P[i] - ch[len - 1])) == -1) len--;
ch[++len] = P[i];
}
return len;
}
int n, t;
int main(){
// ios::sync_with_stdio(false);
// cin.tie(0);cout.tie(0);
scanf("%d", &t);
while(t--){
for(int i = 1; i <= 4; i++) scanf("%lf %lf", &P[i].x, &P[i].y);
L[1] = Line(P[1], P[2]);
L[2] = Line(P[3], P[4]);
if(Line_relation(L[1], L[2]) == 0 || Line_relation(L[1], L[2]) == 1){
printf("0.00\n");
continue;
}
if(Cross_segment1(P[1], P[2], P[3], P[4]) == 0){
printf("0.00\n");
continue;
}
if(P[1].y == P[2].y || P[3].y == P[4].y){
printf("0.00\n");
continue;
}
if(P[1].y < P[2].y) swap(P[1], P[2]);
if(P[3].y < P[4].y) swap(P[3], P[4]);
P[5].x = P[1].x;
P[5].y = 10010;
P[6].x = P[3].x;
P[6].y = 10010;
L[3] = Line(P[1], P[5]);
L[4] = Line(P[3], P[6]);
// cout<<P[1].x<<" "<<P[1].y<<endl;
// cout<<P[2].x<<" "<<P[2].y<<endl;
// cout<<P[3].x<<" "<<P[3].y<<endl;
// cout<<P[6].x<<" "<<P[6].y<<endl;
if(Cross_segment1(P[1], P[5], P[3], P[4]) || Cross_segment1(P[3], P[6], P[1], P[2])){
printf("0.00\n");
continue;
}
P[7] = Cross_point(P[1], P[2], P[3], P[4]);
// cout<<P[1].x<<" "<<P[1].y<<endl;
// cout<<P[3].x<<" "<<P[3].y<<endl;
if(P[1].y < P[3].y){
P[8].y = P[1].y;
if(P[3].x == P[4].x) P[8].x = P[3].x;
else{
double k = (P[3].y - P[4].y) / (P[3].x - P[4].x);
P[8].x = P[3].x - (P[3].y - P[1].y) / k;
}
P[9] = P[1];
}
else {
P[8].y = P[3].y;
if(P[1].x == P[2].x) P[8].x = P[1].x;
else{
double k = (P[1].y - P[2].y) / (P[1].x - P[2].x);
P[8].x = P[1].x - (P[1].y - P[3].y) / k;
// cout<<P[1].x<<" "<<P[1].y<<endl;
// cout<<P[2].x<<" "<<P[2].y<<endl;
// cout<<k<<endl;
}
P[9] = P[3];
// cout<<P[8].x<<" "<<P[8].y<<endl;
}
// cout<<P[8].x<<" "<<P[8].y<<endl;
// cout<<P[9].x<<" "<<P[9].y<<endl;
double area = 0;
area += Cross(P[8] - P[7], P[7] - P[9]);
area /= 2;
area = fabs(area);
printf("%.2f\n", area);
}
return 0;
}
L - Pipe (POJ - 1039)
AC Code:
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 1010;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
int id;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
bool operator < (const Point &b)const{ //凸包排序
if(x == b.x) return y < b.y;
return x < b.x;
}
}P[maxn];
Point ch[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否规范相交 即如果一条线段的一个端点恰在另一条线段上则视为不相交;如果两条线段部分重合,也视为不相交。
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交,端点重合不相交
}
bool Cross_segment1(Point a, Point b, Point c, Point d){ //两线段是否非规范相交
return
max(a.x, b.x) >= min(c.x, d.x)&&
max(c.x, d.x) >= min(a.x, b.x)&&
max(a.y, b.y) >= min(c.y, d.y)&&
max(c.y, d.y) >= min(a.y, b.y)&&
sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
sgn(Cross(c - b, a - b)) * sgn(Cross(d - b, a - b)) <= 0&&
sgn(Cross(a - d, c - d)) * sgn(Cross(b - d, c - d)) <= 0;
}
double Helen(double a, double b, double c){ //海伦公式
double p = (a + b + c)/2;
return sqrt(p * (p - a) * (p - b) * (p - c));
}
int Point_in_polygon(Point pt, Point *p, int n){ //判断点和多边形的位置关系
for(int i = 0; i < n; i++){
if(p[i] == pt) return 3; //点在多边形的顶点上
}
for(int i = 0; i < n; i++){
Line v = Line(p[i], p[(i + 1) % n]);
if(Point_on_seg(pt, v)) return 2; //点在多边形边上
}
int num = 0;
for(int i = 0; i < n; i++){
int j = (i + 1) % n;
int c = sgn(Cross(pt - p[j], p[i] - p[j]));
int u = sgn(p[i].y - pt.y);
int v = sgn(p[j].y - pt.y);
if(c > 0 && u < 0 && v >= 0) num++;
if(c < 0 && u >= 0 && v < 0) num--;
}
return num != 0; //1点在内部; 0点在外部
}
double Polygon_area(Point *p, int n){ //求多边形面积
double area = 0;
for (int i = 0; i < n; ++i)
area += Cross(p[i], p[i + 1]);
return area / 2;
}
Point Polygon_center(Point *p, int n){ //求多边形的重心
Point ans(0, 0);
if(Polygon_area(p, n) == 0) return ans;
for(int i = 0; i < n; i++)
ans = ans + (p[i] + p[(i + 1) % n]) * Cross(p[i], p[(i + 1) % n]);
return ans / Polygon_area(p, n) / 6;
}
int Andrew(int n){ //返回凸包顶点数, 从0到top, ch[top] = ch[0]
sort(P, P + n);
int top = 1;
ch[0] = P[0]; ch[1] = P[1];
for(int i = 2;i < n; i++){
while(top && Cross(P[i] - ch[top - 1], ch[top] - ch[top-1]) > eps) top--;
ch[++top] = P[i];
}
int len = top;
ch[++top] = P[n-2];
for(int i = n-3;i >= 0; i--){
while(top != len && Cross(P[i] - ch[top - 1], ch[top] - ch[top-1]) > eps) top--;
ch[++top] = P[i];
}
return top;
}
bool judgetb(int n){ //判断是否为稳定凸包 即一条边上至少三个点
for(int i = 1;i < n; i++){
if((Cross(ch[i] - ch[i - 1], ch[i] - ch[i + 1])) != 0 && (Cross(ch[i] - ch[(i + 2) % n], ch[i + 1] - ch[(i + 2) % n])) != 0)
return false;
}
return true;
}
int cmp(Point a,Point b){ //极角排序
return Cross(a - P[0], b - P[0]) > 0;
}
int n, flag;
int main(){
// ios::sync_with_stdio(false);
// cin.tie(0);cout.tie(0);
Line v[maxn];
Point p;
while(~scanf("%d", &n)){
if(n == 0) break;
for(int i = 1; i <= n; i++){
scanf("%lf %lf", &P[i].x, &P[i].y);
P[i + n].x = P[i].x;
P[i + n].y = P[i].y - 1;
}
for(int i = 2; i <= n; i++) L[i - 1] = Line(P[i - 1], P[i]);
for(int i = n + 2; i <= 2 * n; i++) L[i - 2] = Line(P[i - 1], P[i]); // L[1] ~ L[2 * n - 2]
for(int i = 1; i <= n; i++) v[i] = Line(P[i], P[i + n]);
double maxx = -inf;
for(int i = 1; i <= n; i++){
for(int j = n + 1; j <= 2 * n; j++){
int sum = 0;
flag = 0;
if(i == j - n) continue;
Line l = Line(P[i], P[j]);
for(int k = 1; k <= n; k++){
p = Cross_point(l.p1, l.p2, v[k].p1, v[k].p2);
if(dcmp(p.y, P[k].y) <= 0 && dcmp(p.y, P[k + n].y) >= 0) sum++;
else{
if(k == 1) break;
else{
if(dcmp(p.y, P[k].y) == 1){
p = Cross_point(l.p1, l.p2, L[k - 1].p1, L[k - 1].p2);
if(dcmp(p.x, maxx) == 1) maxx = p.x;
break;
}
if(dcmp(p.y, P[k + n].y) == -1){
p = Cross_point(l.p1, l.p2, L[k + n - 2].p1, L[k + n - 2].p2);
if(dcmp(p.x, maxx) == 1) maxx = p.x;
break;
}
}
}
}
if(sum == n){
flag = 1;
break;
}
}
if(flag) break;
}
if(flag) puts("Through all the pipe.");
else printf("%.2f\n", maxx);
}
return 0;
}
M - Geometric Shapes (POJ - 3449)
思路: 思路很简单就是判断每个图形的线段是否非规范相交,就是输入输出有点恶心,我用了二维结构体进行存储,感觉方便了很多。然后就是每次输入的时候都输出一下,可以及时发现哪里出问题了。
AC Code:
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
#include<queue>
using namespace std;
#define ll long long
const int maxn = 30;
const double pi = acos((double)(-1));
#define eps 1e-8
char ch, shape[maxn];
int num, insert[maxn][maxn];
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
bool operator < (const Point &b)const{ //凸包排序
if(x == b.x) return y < b.y;
return x < b.x;
}
}P[maxn][maxn];
typedef Point Vector;
struct Line{
Point p1,p2;
int size;
Line(){};
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn][maxn];
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}
bool Cross_segment1(Point a, Point b, Point c, Point d){
//两线段是否非规范相交
return
max(a.x, b.x) >= min(c.x, d.x)&&
max(c.x, d.x) >= min(a.x, b.x)&&
max(a.y, b.y) >= min(c.y, d.y)&&
max(c.y, d.y) >= min(a.y, b.y)&&
sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
}
int main() {
while(~scanf(" %c", &ch)) {
if(ch == '.')
break;
if(ch == '-') {
// for(int i = 0; i < 26; i++)
// printf("%d %d\n", i, L[i][0].size);
for(int i = 0; i < 26; i++) {
if(L[i][0].size == 0) continue;
for(int j = 0; j < 26; j++) {
if(i == j || L[j][0].size == 0) continue;
int f = 0;
for(int k = 0; k < L[i][0].size; k++) {
for(int p = 0; p < L[j][0].size; p++) {
if(Cross_segment1(L[i][k].p1, L[i][k].p2, L[j][p].p1, L[j][p].p2) == 1) {
f = 1;
insert[i][j] = 1;
break;
}
}
if(f)
break;
}
}
}
// for(int i = 0; i < 26; i++) {
// for(int j = 0; j < 26; j++)
// printf("%d %d %d\n", i, j, insert[i][j]);
// } // true
for(int i = 0; i < 26; i++) {
if(L[i][0].size == 0) continue;
int ans = 0;
for(int j = 0; j < 26; j++) {
if(insert[i][j]) ans++;
}
if(ans == 0)
printf("%c has no intersections\n", i + 'A');
else if(ans == 1) {
for(int j = 0; j < 26; j++) {
if(insert[i][j]) {
printf("%c intersects with %c\n", i + 'A', j + 'A');
break;
}
}
}
else if(ans == 2) {
int cnt = 0;
for(int j = 0; j < 26; j++) {
if(insert[i][j]) {
if(cnt == 0) {
printf("%c intersects with %c and ", i + 'A', j + 'A');
cnt++;
}
else if(cnt == 1) {
printf("%c\n", j + 'A');
break;
}
}
}
}
else{
int cnt = 0;
for(int j = 0; j < 26; j++) {
if(insert[i][j]) {
if(cnt == 0) {
printf("%c intersects with %c, ", i + 'A', j + 'A');
cnt++;
}
else if(cnt == ans - 1) {
printf("and %c\n", j + 'A');
break;
}
else{
printf("%c, ", j + 'A');
cnt++;
}
}
}
}
}
memset(P, 0, sizeof(P));
memset(L, 0, sizeof(L));
memset(insert, 0, sizeof(insert));
printf("\n");
continue;
}
int num = ch - 'A';
scanf("%s", shape);
// printf("%c %s\n", ch, shape);
if(shape[0] == 's') {
scanf(" (%lf,%lf) (%lf,%lf)", &P[num][0].x, &P[num][0].y, &P[num][2].x, &P[num][2].y);
// printf("%f %f %f %f\n", P[num][0].x, P[num][0].y, P[num][1].x, P[num][1].y);
P[num][1].x = (P[num][0].x + P[num][0].y + P[num][2].x - P[num][2].y) / 2;
P[num][1].y = (-P[num][0].x + P[num][0].y + P[num][2].x + P[num][2].y) / 2;
P[num][3].x = (P[num][0].x - P[num][0].y + P[num][2].x + P[num][2].y) / 2;
P[num][3].y = (P[num][0].x + P[num][0].y - P[num][2].x + P[num][2].y) / 2;
for(int i = 0; i < 4; i++) {
L[num][i] = Line(P[num][i], P[num][(i + 1) % 4]);
}
L[num][0].size = 4;
// printf("%d %d\n", num, L[num][0].size);
} //true
else if(shape[0] == 'l') {
scanf(" (%lf,%lf) (%lf,%lf)", &P[num][0].x, &P[num][0].y, &P[num][1].x, &P[num][1].y);
L[num][0] = Line(P[num][0], P[num][1]);
L[num][0].size = 1;
// printf("%f %f %f %f\n", L[num][0].p1.x, L[num][0].p1.y, L[num][0].p2.x, L[num][0].p2.y);
// printf("%d %d\n", num, L[num][0].size);
} // true
else if(shape[0] == 't') {
scanf(" (%lf,%lf) (%lf,%lf) (%lf,%lf)", &P[num][0].x, &P[num][0].y, &P[num][1].x, &P[num][1].y, &P[num][2].x, &P[num][2].y);
for(int i = 0; i < 3; i++) {
L[num][i] = Line(P[num][i], P[num][(i + 1) % 3]);
}
// for(int i = 0; i < 3; i++)
// printf("%f %f %f %f\n", L[num][i].p1.x, L[num][i].p1.y, L[num][i].p2.x, L[num][i].p2.y);
L[num][0].size = 3;
// printf("%d %d\n", num, L[num][0].size);
} // true
else if(shape[0] == 'p') {
int cnt;
scanf("%d", &cnt);
for(int i = 0; i < cnt; i++) {
scanf(" (%lf,%lf)", &P[num][i].x, &P[num][i].y);
}
for(int i = 0; i < cnt; i++) {
L[num][i] = Line(P[num][i], P[num][(i + 1) % cnt]);
}
// for(int i = 0; i < cnt; i++)
// printf("%f %f %f %f\n", L[num][i].p1.x, L[num][i].p1.y, L[num][i].p2.x, L[num][i].p2.y);
L[num][0].size = cnt;
// printf("%d %d\n", num, L[num][0].size);
} // true
else{
scanf(" (%lf,%lf) (%lf,%lf) (%lf,%lf)", &P[num][0].x, &P[num][0].y, &P[num][1].x, &P[num][1].y, &P[num][2].x, &P[num][2].y);
P[num][3].x = P[num][0].x + P[num][2].x - P[num][1].x;
P[num][3].y = P[num][0].y + P[num][2].y - P[num][1].y;
for(int i = 0; i < 4; i++) {
L[num][i] = Line(P[num][i], P[num][(i + 1) % 4]);
}
// for(int i = 0; i < 4; i++)
// printf("%f %f %f %f\n", L[num][i].p1.x, L[num][i].p1.y, L[num][i].p2.x, L[num][i].p2.y);
L[num][0].size = 4;
// printf("%d %d\n", num, L[num][0].size);
// printf("%d\n", L[num][3].size);
} // true
}
system("pause");
return 0;
}
N - A Round Peg in a Ground Hole (POJ - 1548)
思路:
- 如果不是凸包输出"HOLE IS ILL-FORMED"
- 如果是凸包但圆不在凸包内输出"PEG WILL NOT FIT"
- 如果是凸包并且圆在凸包内输出"PEG WILL FIT"
对于如何判断圆是否在凸包内可先判断圆心是否在凸包内,再判断圆到每条边的距离(三角形面积除底)是否小于半径。
这题点的坐标可能是乱序的,所以需要极角排序。
AC Code:
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
#include<queue>
using namespace std;
#define ll long long
const int maxn = 1010;
const double pi = acos((double)(-1));
#define eps 1e-8
int n;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
bool operator < (const Point &b)const{ //凸包排序
if(x == b.x) return y < b.y;
return x < b.x;
}
}P[maxn], ch[maxn];
typedef Point Vector;
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;}
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
struct Line{
Point p1,p2;
Line(){};
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
int Andrew(int n) { //0 ~ top - 1 ch[top] = ch[0]
sort(P, P + n);
int top = 0;
for(int i = 0; i < n; i++) {
while(top > 1 && Cross(ch[top - 1] - ch[top - 2], P[i] - ch[top - 2]) < 0) {
top--;
}
ch[top++] = P[i];
}
int k = top;
for(int i = n - 2; i >= 0; i--) {
while(top > k && Cross(ch[top - 1] - ch[top - 2], P[i] - ch[top - 2]) < 0) {
top--;
}
ch[top++] = P[i];
}
if(n > 1)
top--;
return top;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 &&
sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
int Point_in_polygon(Point pt, Point *p, int n){ //判断点和多边形的位置关系
for(int i = 0; i < n; i++){
if(p[i] == pt) return 3; //点在多边形的顶点上
}
for(int i = 0; i < n; i++){
Line v = Line(p[i], p[(i + 1) % n]);
if(Point_on_seg(pt, v)) return 2; //点在多边形边上
}
int num = 0;
for(int i = 0; i < n; i++){
int j = (i + 1) % n;
int c = sgn(Cross(pt - p[j], p[i] - p[j]));
int u = sgn(p[i].y - pt.y);
int v = sgn(p[j].y - pt.y);
if(c > 0 && u < 0 && v >= 0) num++;
if(c < 0 && u >= 0 && v < 0) num--;
}
return num != 0; //1点在内部; 0点在外部
}
struct Circle{
double x, y, r;
}C;
bool check() {
Point p = Point(C.x, C.y);
if(Point_in_polygon(p, P, n) == 0) return false;
for(int i = 0; i < n; i++) {
if(sgn(C.r - fabs(Cross(P[i] - p, P[(i + 1) % n] - p) / Dist(P[i], P[(i + 1) % n]))) > 0 ) {
return false;
}
}
return true;
}
int cmp(Point a,Point b){ //极角排序
Point pp = Point(0, 0);
return Cross(a - pp, b - pp) > 0;
}
int main() {
while(~scanf("%d", &n)) {
if(n < 3)
break;
scanf("%lf %lf %lf", &C.r, &C.x, &C.y);
for(int i = 0; i < n; i++)
scanf("%lf %lf", &P[i].x, &P[i].y);
int len = Andrew(n);
if(len == n) {
sort(P, P + n, cmp);
if(check()) {
puts("PEG WILL FIT");
}
else{
puts("PEG WILL NOT FIT");
}
}
else{
puts("HOLE IS ILL-FORMED");
}
}
system("pause");
return 0;
}