kuangbin专题十三-基础计算几何
链接:https://cn.vjudge.net/contest/68968
题意:m个玩具落在n+1个区间,给你玩具的坐标,问每个区间有多少玩具。
思路:叉积的简单应用,用叉积判断在直线的哪一侧,因为是顺序给出坐标,所以从左往右判断即可。
AC代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 5e3 + ;
int U[maxn], L[maxn], ans[maxn];
int Cross(int x1, int y1, int x2, int y2)
{
return x1 * y2 - x2 * y1;
}
int main()
{
int n, m, x1, y1, x2, y2;
int a, b;
while(~scanf("%d",&n) && n)
{
scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
for(int i = ;i < n;i++)
{
scanf("%d %d",&U[i], &L[i]);
}
for(int i = ;i <= n;i++) ans[i] = ;
while(m--)
{
scanf("%d%d",&a, &b);
int i = ;
for(i = ;i < n;i++)
{
if(Cross(a - L[i], b - y2, U[i] - L[i], y1 - y2) <= ) break;
}
ans[i]++;
}
for(int i = ;i <= n;i++) printf("%d: %d\n",i, ans[i]);
printf("\n");
}
return ;
}
题意:同上一题类似,不过需要排序和改变输出。
AC代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 5e3 + ;
int U[maxn], L[maxn], ans[maxn], num[maxn];
int Cross(int x1, int y1, int x2, int y2)
{
return x1 * y2 - x2 * y1;
}
int main()
{
int n, m, x1, y1, x2, y2;
int a, b;
while(~scanf("%d",&n) && n)
{
scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
for(int i = ;i < n;i++)
{
scanf("%d %d",&U[i], &L[i]);
}
sort(U, U + n);
sort(L, L + n);
for(int i = ;i <= n;i++) ans[i] = num[i] = ;
while(m--)
{
scanf("%d%d",&a, &b);
int i = ;
for(i = ;i < n;i++)
{
if(Cross(a - L[i], b - y2, U[i] - L[i], y1 - y2) <= ) break;
}
num[i]++;
}
for(int i = ;i <= n;i ++) ans[num[i]] ++;
printf("Box\n");
for(int i = ;i <= n;i++)if(ans[i]) printf("%d: %d\n",i, ans[i]);
}
return ;
}
题意:给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!。
思路:枚举所有端点,判断与其他线段相不相交,至于为什么,画个图吧,反正我理解挺久的。
AC代码:
#include<cstdio>
#include<cmath>
using namespace std;
const double eps = 1e-;
struct Point{
double x, y;
Point(double _x = , double _y = ):x(_x),y(_y){}
};
double Multi(Point p1, Point p2, Point p0) {
return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
}
int n;
struct Line{
Point a, b;
};
Line line[];
bool check(Point a, Point b)
{
if(fabs(a.x - b.x) < eps && fabs(a.y - b.y) < eps) return false;
for(int i = ;i < n;i++)
{
if (Multi(line[i].a, b, a) * Multi(line[i].b, b, a) > ) return false; }
return true;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
double x1, y1, x2, y2;
for(int i = ;i < n;i++)
{
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
line[i].a = Point(x1, y1);
line[i].b = Point(x2, y2);
}
if(n == ){ printf("Yes!\n");continue;}
bool flag = false;
for(int i = ;i < n && !flag;i++)
{
if (check(line[i].a, line[i].b)) flag = true;
for(int j = i + ;j < n && !flag;j++)
{
if(check(line[i].a, line[j].a) ||
check(line[i].a, line[j].b) ||
check(line[i].b, line[j].a) ||
check(line[i].b, line[j].b))
flag = true;
}
}
if(flag) printf("Yes!\n");
else printf("No!\n");
}
return ;
}
题意:俩条直线相交,相交则输出交点。
AC代码:
#include<cstdio>
#include<cmath>
using namespace std;
const double eps = 1e-;
struct Point{
double x, y;
Point(double _x = , double _y = ):x(_x),y(_y){}
}a, b, c, d;
typedef Point Vector;
Vector operator - (Point A, Point 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); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//叉积
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){
Vector u = P - Q;
double t = Cross(w,u)/Cross(v,w);
return P + v*t;
}
int main()
{
int n;
scanf("%d",&n);
printf("INTERSECTING LINES OUTPUT\n");
while(n--)
{
scanf("%lf %lf %lf %lf",&a.x, &a.y, &b.x, &b.y);
scanf("%lf %lf %lf %lf",&c.x, &c.y, &d.x, &d.y);
if(Cross(a - c, b - c) == && Cross(a - d, b - d) == )
printf("LINE\n");
else if(Cross(a - b, c- d) == )
printf("NONE\n");
else
{
Point p = GetLineIntersection(a, a-b, c, c-d);
printf("POINT %.2f %.2f\n",p.x,p.y);
}
}
printf("END OF OUTPUT\n");
return ;
}
题意:问你从(0,5) - > (10, 5)的最短路。
思路:枚举所有端点,如果确定和其他线段不规范相交,则加入这条路径,然后拿Floyd去跑最短路即可。
AC代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const double eps = 1e-;
const int maxn = 1e3 + ;
const double inf = 1e20;
struct Point{
double x, y;
Point(double _x = , double _y = ):x(_x),y(_y){}
};
typedef Point Vector;
Vector operator - (Point A, Point 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); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý
int dcmp(double x){
if(fabs(x) < eps) return ; else return x < ? - : ;
}
double distant(Point a, Point b){
double x = a.x - b.x;
double y = a.y - b.y;
return sqrt(x*x + y*y);
}
bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
{
double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
return dcmp(c1)*dcmp(c2) < && dcmp(c3)*dcmp(c4) < ;
}
struct edge{
Point from, to;
edge(){}
edge(Point a, Point b){ from = a,to = b;}
};
Point p[maxn];
edge e[maxn];
double d[maxn][maxn];
int n, tot, cnt;
bool check(Point a, Point b)
{
for(int i = ;i < tot;i++)
if(SegmentProperIntersection(a, b, e[i].from, e[i].to))
{
return false;
} return true;
}
int main()
{
while(~scanf("%d",&n) && n != -)
{
tot = cnt = ;
double x, y1, y2, y3, y4;
p[cnt++] = Point(, );
for(int i = ;i < n;i++)
{
scanf("%lf%lf%lf%lf%lf",&x, &y1, &y2, &y3, &y4);
p[cnt++] = Point(x, y1);
p[cnt++] = Point(x, y2);
p[cnt++] = Point(x, y3);
p[cnt++] = Point(x, y4);
e[tot++] = edge(Point(x, ), Point(x, y1));
e[tot++] = edge(Point(x, y2), Point(x, y3));
e[tot++] = edge(Point(x, y4), Point(x, ));
}
p[cnt++] = Point(, );
for(int i = ;i < cnt;i++)
for(int j = ;j < cnt;j++)
d[i][j] = inf;
for(int i = ; i < cnt;i++)
{
for(int j = i + ;j < cnt;j ++)
{
if(fabs(p[i].x - p[j].x)< eps)continue;
if(check(p[i], p[j]))
{
d[i][j] = d[j][i] = distant(p[i], p[j]);
}
}
}
for(int k = ;k < cnt;k++)
for(int i = ;i < cnt;i++)
for(int j = ;j < cnt;j++)
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
printf("%.2f\n",d[][cnt - ]);
}
return ;
}
题意:筷子一根一根丢,问哪些筷子没被压着。
思路:所有和新加入的线段规范相交的线段标记,最后未标记的输出。
AC代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const double eps = 1e-;
const int maxn = 1e5 + ;
const double inf = 1e20;
struct Point{
double x, y;
Point(double _x = , double _y = ):x(_x),y(_y){}
};
typedef Point Vector;
Vector operator - (Point A, Point 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); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý
int dcmp(double x){
if(fabs(x) < eps) return ; else return x < ? - : ;
}
double distant(Point a, Point b){
double x = a.x - b.x;
double y = a.y - b.y;
return sqrt(x*x + y*y);
}
bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
{
double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
return dcmp(c1)*dcmp(c2) < && dcmp(c3)*dcmp(c4) < ;
}
struct Line{
Point from, to;
Line(){}
Line(Point a, Point b){ from = a,to = b;}
};
Line line[maxn];
bool check(Line a, Line b)
{
return SegmentProperIntersection(a.from, a.to, b.from, b.to);
}
int vis[maxn];
int n, tot, cnt;
int main()
{
while(~scanf("%d",&n) && n)
{
double x1, y1, x2, y2;
for(int i = ;i < n;i++)
{
scanf("%lf %lf %lf %lf",&x1, &y1, &x2, &y2);
line[i] = Line( Point(x1, y1), Point(x2, y2) );
vis[i] = ;
}
for(int i = ;i < n;i++){
for(int j = i + ;j < n;j++)
{
if(check(line[i], line[j]))
{
vis[i] = ;break;
}
}
}
printf("Top sticks: ");
bool flag = true;
for(int i = ;i < n;i++)
{
if(!vis[i])
{
if(flag) flag = false;
else printf(", ");
printf("%d",i + );
}
}
printf(".\n");
}
return ;
}
题意:给你一个房间,房间内有很多墙,再给你个宝藏的坐标,你将从外面砸墙而入,问:你炸墙进去通过的最少的墙的1数目是多少。
思路:枚举线段的端点和宝藏位置的连线,看看和几个线段相交,要加上最外围的墙,所以ans从1开始。
AC代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const double eps = 1e-;
const int maxn = 1e5 + ;
const int inf = 0x3f3f3f3f;
struct Point{
double x, y;
Point(double _x = , double _y = ):x(_x),y(_y){}
};
typedef Point Vector;
Vector operator - (Point A, Point 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); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý
int dcmp(double x){
if(fabs(x) < eps) return ; else return x < ? - : ;
}
double distant(Point a, Point b){
double x = a.x - b.x;
double y = a.y - b.y;
return sqrt(x*x + y*y);
}
bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
{
double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
return dcmp(c1)*dcmp(c2) < && dcmp(c3)*dcmp(c4) < ;
}
struct Line{
Point from, to;
Line(){}
Line(Point a, Point b){ from = a,to = b;}
};
Point p[maxn];
Line line[maxn];
int vis[maxn];
int n, tot, cnt;
int check(Point b, Point a)
{
int ans = ;
for(int i = ;i < tot;i++)
{
if(SegmentProperIntersection(line[i].from, line[i].to, b, a))
ans ++;
}
return ans;
}
int main()
{
while(~scanf("%d",&n))
{
if(n == )
{
printf("Number of doors = 1\n");return ;
}
double x1, x2, y1, y2;
double x, y;
tot = cnt = ;
int ans = inf;
for(int i = ;i < n;i++)
{
scanf("%lf %lf %lf %lf",&x1 ,&y1, &x2, &y2);
p[cnt++] = Point(x1, y1);
p[cnt++] = Point(x2, y2);
line[tot++] = Line(Point(x1, y1), Point(x2, y2));
}
scanf("%lf %lf",&x, &y);
Point A = Point(x, y);
for(int i = ;i < cnt;i++)
{
ans = min(ans, check(A, p[i]));
}
printf("Number of doors = %d\n",ans);
}
return ;
}
题意:问直线和矩形是否相交。
思路:这题有坑,这矩形居然是实的,所以要特判一些情况。
AC代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const double eps = 1e-;
const int maxn = 1e5 + ;
const int inf = 0x3f3f3f3f;
struct Point{
double x, y;
Point(double _x = , double _y = ):x(_x),y(_y){}
};
typedef Point Vector;
Vector operator - (Point A, Point 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); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
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; }//点积
int dcmp(double x){
if(fabs(x) < eps) return ; else return x < ? - : ;
}
double distant(Point a, Point b){
double x = a.x - b.x;
double y = a.y - b.y;
return sqrt(x*x + y*y);
}
bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
{
double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
return dcmp(c1)*dcmp(c2) < && dcmp(c3)*dcmp(c4) < ;
}
struct Line{
Point from, to;
Line(){}
Line(Point a, Point b){ from = a,to = b;}
};
bool check(Line a, Line b){
return SegmentProperIntersection(a.from, a.to, b.from, b.to);
}
bool OnSegment(Point p, Point a1, Point a2){//判断端点在线段上
return dcmp(Cross(a1 - p, a2 - p)) == && dcmp(Dot(a1 - p,a2 - p)) < ;
}
bool check2(Point b, Line a){
return OnSegment(b, a.from, a.to);
}
int n;
int main()
{
scanf("%d",&n);
double x1, y1, x2, y2;
double x3, y3, x4, y4;
while(n--)
{
bool flag = false;
scanf("%lf %lf %lf %lf",&x1, &y1, &x2, &y2);
Point E = Point(x1, y1);
Point F = Point(x2, y2);
Line L = Line(E, F);
scanf("%lf %lf %lf %lf",&x3, &y3, &x4, &y4);
if(x3 > x4) swap(x3, x4);
if(y3 < y4) swap(y3, y4);
Point A = Point(x3, y3);
Point B = Point(x3, y4);
Point C = Point(x4, y4);
Point D = Point(x4, y3);
Line AB = Line(A, B);
Line CB = Line(C, B);
Line CD = Line(C, D);
Line AD = Line(A, D);
if(x1 >= x3 && x1 <= x4 && y1 <= y3 && y1 >= y4) flag = true;
if(check(AB, L) || check(CD, L) || check(AD, L) || check(CB, L))
flag = true;
if(check2(A, L) || check2(B, L) || check2(C, L) || check2(D, L))
flag = true;
if(check2(E, AB) || check2(E, CD) || check2(E, AD) || check2(E, CB))
flag = true;
if(check2(F, AB) || check2(F, CD) || check2(F, AD) || check2(F, CB))
flag = true;
if(flag) printf("T\n");
else printf("F\n");
}
return ;
}
题意:一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.
思路:这题用极角排序,边排序边输出orz。
AC代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const double eps = 1e-;
const int maxn = 1e3+ ;
const int inf = 0x3f3f3f3f;
struct Point{
double x, y;
int num;
Point(double _x = , double _y = ):x(_x),y(_y){}
};
typedef Point Vector;
Vector operator - (Point A, Point 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); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
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; }//点积
int dcmp(double x){
if(fabs(x) < eps) return ; else return x < ? - : ;
}
double distant(Point a, Point b){
double x = a.x - b.x;
double y = a.y - b.y;
return sqrt(x*x + y*y);
}
Point p[maxn];
int pos;
bool cmp(const Point a, const Point b){
int temp = Cross(p[pos] - a,p[pos] - b);
if(temp > ) return true;
else if(temp == && distant(p[pos], a) < distant(p[pos], b))
return true;
return false;
}
int n;
int main()
{
int t;
scanf("%d",&t);
while (t--){
scanf("%d",&n);
for (int i = ; i < n; ++i) {
scanf("%d %lf %lf",&p[i].num, &p[i].x, &p[i].y);
if(p[i].y < p[].y || (p[i].y == p[].y && p[i].x < p[].x))
swap(p[i],p[]);
}
pos = ;
printf("%d",n);
for(int i = ;i < n;++i){
sort(p + i,p + n, cmp);
pos++;
}
for (int i = ; i < n; ++i) {
printf(" %d",p[i].num);
}
printf("\n");
}
return ;
}
思路:这题在网上扒了一个不是几何的做法,具体看代码吧。
AC代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = ;
struct node{
int l, r, len;
};
node a[maxn];
int n;
int main()
{
while(~scanf("%d",&n) && n)
{
memset(a,,sizeof(a));
for(int i = ;i < n;i++)
{
scanf("%d",&a[i].len);
for(int j = ;j < i;j ++)
{
a[i].l = max(a[i].l, a[j].r - abs(a[i].len - a[j].len));
}
a[i].r = a[i].l + *a[i].len;
}
for(int i = ;i < n;i++)
{
for(int j = ;j < i;j ++)
{
if(a[i].l < a[j].r)
{
if(a[j].len < a[i].len) a[j].r = a[i].l;
else a[i].l = a[j].r;
}
}
}
bool flag = false;
for(int i = ;i < n;i++)
{
if(a[i].l < a[i].r)
{
if(!flag) printf("%d",i + ),flag = true;
else printf(" %d",i+);
}
}
printf("\n");
}
return ;
}
题意:两根木棍,摆放的方式由题目给出,问接到雨水的量是多少。(注意是平面,只要考虑面积)
思路:这题不看题解真想不到,简直天坑,点题解一看图就懂了,太多特殊情况了。最后所有都特判了,结果答案还要加个eps才能过orz,醉了!
AC代码:
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const double eps = 1e-;
int sgn(double x){
if(fabs(x) < eps) return ;
else return x < ? - : ;
}
struct Point{
double x, y;
Point(){}
Point(double _x, double _y){
x = _x, y = _y;
}
Point operator - (const Point &b){
return Point(x - b.x, y - b.y);
}
double operator * (const Point &b){
return x*b.x + y*b.y;
}
double operator ^ (const Point &b){
return x*b.y - y* b.x;
}
};
struct Line{
Point s, e;
Line(){}
Line(Point _s, Point _e){
s = _s, e = _e;
}
int segcrossing(Line v)
{
int d1 = sgn((e - s)^(v.s - s));
int d2 = sgn((e - s)^(v.e - s));
int d3 = sgn((v.e - v.s)^(s - v.s));
int d4 = sgn((v.e - v.s)^(e - v.s));
if( (d1^d2) == - && (d3^d4) == - )return ;
return
(d1 == && sgn((v.s - s)*(v.s - e)) <= ) ||
(d2 == && sgn((v.e - s)*(v.e - e)) <= ) ||
(d3 == && sgn((s - v.s)*(s - v.e)) <= ) ||
(d4 == && sgn((e - v.s)*(e - v.e)) <= );
}
Point crosspoint(Line v){
double a1 = (v.e - v.s)^(s - v.s);
double a2 = (v.e - v.s)^(e - v.s);
return Point((s.x*a2 - e.x*a1)/(a2 - a1),(s.y*a2 - e.y*a1)/(a2 - a1));
}
};
int main()
{
double x1, x2, x3, x4, y1, y2, y3, y4;
Line A, B;
int t;
scanf("%d",&t);
while(t--){
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
scanf("%lf%lf%lf%lf", &x3, &y3, &x4, &y4);
A = Line(Point(x1, y1),Point(x2, y2));
B = Line(Point(x3, y3),Point(x4, y4));
if(sgn(A.s.y - A.e.y) == || sgn(B.s.y - B.e.y) == )
{
printf("0.00\n");
continue;
}
if(sgn((A.s - A.e)^(B.s - B.e)) == )
{
printf("0.00\n");
continue;
}
//高的点放 s.y下面会用到
if(sgn(A.s.y - A.e.y) < ) swap(A.s, A.e);
if(sgn(B.s.y - B.e.y) < ) swap(B.s, B.e); if(A.segcrossing(B) == )
{
printf("0.00\n");
continue;
}
//口被封掉的情况
if(B.segcrossing(Line(A.s,Point(A.s.x,))) )
{
printf("0.00\n");
continue;
}
if(A.segcrossing(Line(B.s,Point(B.s.x,))) )
{
printf("0.00\n");
continue;
}
Point C = A.crosspoint(B);
//printf("%f %f",C.x,C.y);
double ans1,ans2;
Point D = A.crosspoint(Line(Point(,B.s.y),B.s));
//printf("%f %f",D.x,D.y);
ans1 = fabs( (B.s - C) ^ (D - C) )/2.0;
Point E = B.crosspoint(Line(Point(,A.s.y),A.s));
ans2 = fabs( (A.s - C) ^ (E - C) )/2.0;
double ans = min(ans1,ans2);
printf("%.2f\n",ans +eps);
}
return ;
}
题意:有一宽度为1的折线管道,上面顶点为(xi,yi),所对应的下面顶点为(xi,yi-1),假设管道都是不透明的,不反射的,光线从左边入口处的(x1,y1),(x1,y1-1)之间射入,向四面八方传播,求解光线最远能传播到哪里(取x坐标)或者是否能穿透整个管道。
思路:因为WA到自闭。于是改用kuangbin大佬的板子,于是就过了,orz!板子很重要。能到达最远的光线一定是某一上端点和某一下端点的连线,枚举判断。
AC代码:
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const double eps = 1e-;
const int maxp = ;
int sgn(double x){
if(fabs(x) < eps) return ;
else return x < ? - : ;
}
struct Point{
double x, y;
Point(){}
Point(double _x, double _y){
x = _x, y = _y;
}
Point operator -(const Point &b)const{
return Point(x - b.x, y - b.y);
}
double operator *(const Point &b)const{
return x*b.x + y*b.y;
}
double operator ^(const Point &b)const{
return x*b.y - y*b.x;
}
bool operator == (Point b) const{
return sgn(x - b.x) == && sgn(y - b.y) == ;
}
bool operator < (Point b)const{
return sgn(x - b.x) == ? sgn(y - b.y < ) : x < b.x;
}
};
struct Line{
Point s, e;
Line(){}
Line(Point _s, Point _e){s = _s, e = _e;}
bool operator == (Line v){
return (s == v.s) && (e == v.e);
}
int linecrossing(Line v){
int d1 = sgn((e - s) ^ (v.s - s));
int d2 = sgn((e - s) ^ (v.e - s));
if( (d1 ^ d2) == -) return ;
else return (d1 == ) || (d2 == );
}
Point crosspoint(Line v){
double a1 = (v.e - v.s)^(s - v.s);
double a2 = (v.e - v.s)^(e - v.s);
return Point((s.x*a2 - e.x*a1)/(a2 - a1),(s.y*a2 - e.y*a1)/(a2 - a1));
}
};
Point up[maxp], down[maxp];
int main()
{
int n;
Line A;
while(~scanf("%d",&n) && n)
{
for(int i = ;i < n;i++)
{
scanf("%lf %lf",&up[i].x, &up[i].y);
down[i].x = up[i].x, down[i].y = up[i].y - ;
}
bool flag = false;
double ans = -100000000.0;
for(int i = ;i < n;i++)
{
for(int j = ;j < n;j++)
{
int k;
A = Line(up[i], down[j]);
for(k = ;k < n;k++){
if(!A.linecrossing(Line(up[k], down[k])) )
{
break;
}
}
if(k >= n){flag = true;break;}
if(k > max(i, j))
{
if(A.linecrossing(Line(up[k], up[k-])))
{
Point x = A.crosspoint(Line(up[k], up[k-]));
ans = max(ans,x.x);
}
if(A.linecrossing(Line(down[k], down[k-])))
{
Point x = A.crosspoint(Line(down[k], down[k-]));
ans = max(ans,x.x);
}
}
if(flag) break;
}
}
if(flag) printf("Through all the pipe.\n");
else printf("%.2f\n",ans + eps);
}
return ;
}
POJ 3449 Geometric Shapes
POJ 1584 A Round Peg in a Ground Hole
kuangbin专题十三-基础计算几何的更多相关文章
- kuangbin专题 数论基础 part1?
线段树专题太难了,那我来做数学吧! 但数学太难了,我......(扯 这两天想了做了查了整理了几道数学. 除了一些进阶的知识,像莫比乌斯反演,杜教筛,min25学不会我跳了,一些基础的思维还是可以记录 ...
- [kuangbin]专题六 最小生成树 题解+总结
kuangbin专题链接:https://vjudge.net/article/752 kuangbin专题十二 基础DP1 题解+总结:https://www.cnblogs.com/RioTian ...
- Kuangbin 带你飞-基础计算几何专题 题解
专题基本全都是模版应用.贴一下模版 平面最近点对 const double INF = 1e16; ; struct Point { int x,y; int type; }; double dist ...
- 【kuangbin专题】计算几何_半平面交
1.poj3335 Rotating Scoreboard 传送:http://poj.org/problem?id=3335 题意:就是有个球场,球场的形状是个凸多边形,然后观众是坐在多边形的边上的 ...
- 【kuangbin专题】计算几何_凸包
1.poj1113 Wall 题目:http://poj.org/problem?id=1113 题意:用一条线把若干个点包起来,并且线距离任何一个点的距离都不小于r.求这条线的最小距离是多少? 分析 ...
- aria2 源码解析专题—— (一)基础架构
此文章是这个专题的开篇,由于初入 C++ 的大门,所以想着拿个项目来看看,凑巧有点基础,又想学习一下在unix上的编程,所以就找了 aria2 这个库来看看源码,希望能学到一些东西. 言归正传,今天把 ...
- [原]最短路专题【基础篇】(updating...)
hud1548 a strange lift 最短路/bfs 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1548 题意:一个奇怪的电梯,每层楼的 ...
- R语言︱SNA-社会关系网络 R语言实现专题(基础篇)(一)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 笔者寄语:这里所有的应用代码都来自与igrap ...
- LightOJ 1062 - Crossed Ladders 基础计算几何
http://www.lightoj.com/volume_showproblem.php?problem=1062 题意:问两条平行边间的距离,给出从同一水平面出发的两条相交线段长,及它们交点到水平 ...
随机推荐
- 实用maven笔记二-信息&依赖管理
目前我经历的公司的主要项目管理工具都是maven,maven除了是一个实用的构建工具外,也是一个功能强大的项目管理工具.其管理功能分为信息管理和依赖管理.通过pom.xml文件实现. 信息管理 信息管 ...
- Python- 接口类-抽象类
接口类 继承有两种用途: 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接 ...
- Python之字符串搜索和替换
简单直接使用 str.replace() text="zzy is a beautiful boy" print(text.replace("boy",&quo ...
- 在egg中配置 sequelize
如何在eggjs中引入 sequlize 安装 第一步,在项目中安装 egg-sequelize插件和mysql插件 npm install --save egg-sequelize mysql2 第 ...
- 2019-8-31-matlab-画图
title author date CreateTime categories matlab 画图 lindexi 2019-08-31 16:55:59 +0800 2018-2-13 17:23: ...
- nginx proxy_pass设置
NGINX服务器的反向代理PROXY_PASS配置方法讲解 https://www.cnblogs.com/lianxuan1768/p/8383804.html Nginx配置proxy_pass转 ...
- jieba分词单例模式及linux权限不够情况下tmp_dir自定义
在linux环境下,没有root权限的情况下,有时会碰到如下问题: Building prefix dict from the default dictionary ... Loading model ...
- CreateFile的内部实现
今天想看看CreateFile的内部实现,不过网上没有想要的资料,都只是对参数分析了一下.找了找WRK源码,找到CreateFile的源码自己来分析一下. HANDLE WINAPI CreateFi ...
- list集合获取相同以及不同的对象
List<StyleMenuModule> list1 = new ArrayList<>(); StyleMenuModule s1 = new StyleMenuModul ...
- 高性能js之js文件的加载与解析
随着网站的发展,现在的网页已经离不开js,经常一个页面会引入大量的js.那么该如何合理的加载这些js? head标签中引入js文件可能是最常见的一种方式,但是这样会造成一个问题.因为j可以说是浏览器中 ...