链接: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