AC is lucky , WA is life.
问题虫洞——A: A - TOYS
问题虫洞——B: B - Toy Storage
两题个大致思想相同,参考我的另一篇博客吧!:TOYS POJ - 2318 (二分+斜率)
问题虫洞——C: C - Segments
黑洞内窥:
t组样例,每组样例给出n条线段的两个端点坐标
问是否存在这样一条直线,所以线段在该线段上的投影有公共点。
思维光年:
问题可以转换为:是否存在一条直线,使得该直线与所有的线段相交。
然后你枚举所有线段的端点连线,判断是否与所有线段相交即可:
ACcode:
//#include<bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include<algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <stdlib.h>
#include <cstring>
#include <string.h>
#include <string>
#include <math.h>
#include <sstream>
using namespace std;
typedef long long int ll;
const ll MAXN = 1005;
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll
const ll mod = 100000007;
const double eps = 0.00000001;
struct node
{
double x1, y1, x2, y2;
} stu[MAXN];
int n, t;
double go(double x1, double y1, double x2, double y2)
{
return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}
double cha(double x1,double y1,double x2,double y2,double x,double y)
{
return (x2-x1)*(y-y1)-(x-x1)*(y2-y1);
}
int so(double x1, double y1, double x2, double y2)
{
if(go(x1, y1, x2, y2) < eps) return 0;//可能点重合
for(int i=0; i<n; ++i)
{
if(cha(x1, y1, x2, y2, stu[i].x1, stu[i].y1) * cha(x1, y1, x2, y2, stu[i].x2, stu[i].y2)>eps)
return 0;
}
return 1;
}
int main()
{
cin >> t;
while(t--)
{
scanf("%d", &n);
for(int i=0; i<n; ++i)
scanf("%lf %lf %lf %lf", &stu[i].x1, &stu[i].y1, &stu[i].x2, &stu[i].y2);
if(n == 1) {
puts("Yes!");
continue;
}
int flag = 0;
for(int i=0; i<n && !flag; ++i)
{
for(int j= i+1; j<n && !flag; ++j)
if(so(stu[i].x1, stu[i].y1, stu[j].x1, stu[j].y1) || so(stu[i].x1, stu[i].y1, stu[j].x2, stu[j].y2) || so(stu[i].x2, stu[i].y2, stu[j].x1, stu[j].y1) || so(stu[i].x2, stu[i].y2, stu[j].x2, stu[j].y2))
flag = 1;
}
if(flag) puts("Yes!");
else puts("No!");
}
return 0;
}
问题虫洞——D: D - Intersecting Lines
黑洞内窥:
n组样例,每组样例给出两条线段的坐标,即八个点坐标
问每组样例的两条线段是平行,重合还是相交
如果相交,请输出交点。
思维光年:
枚举两条线段的所以情况;
ACcode:
//#include<bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include<algorithm>
#include <map>
#include <set>
//#include <vector>
//#include <queue>
//#include <stack>
#include <stdlib.h>
#include <cstring>
#include <string.h>
#include <string>
#include <math.h>
#include <sstream>
using namespace std;
typedef long long int ll;
const ll MAXN = 5005;
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll
const ll mod = 100000007;
const double eps = 0.0000001;
int main()
{
int t;
cin >> t;
puts("INTERSECTING LINES OUTPUT");
while(t--)
{
double x1, y1, x2, y2, x3, y3, x4, y4;
scanf("%lf %lf %lf %lf %lf %lf %lf %lf", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4);
double a1=0, b1=0, a2=0, b2=0;
int f1 = 0, f2 = 0;//判断线段1和2是否垂直x轴
if(x1 == x2) f1 = 1;//垂直无斜率
else {
a1 = (y2 - y1)/(x2 - x1);
b1 = y1 - a1*x1;
}
if(x3 == x4) f2 = 1;
else {
a2 = (y4 - y3)/(x4 - x3);
b2 = y3 - a2*x3;
}
if(f1 && f2 && x1!=x3) puts("NONE");
else if(f1 && f2 && x1 == x3) puts("LINE");
else if(f1 && !f2)
{
double x = x1;
double y = a2*x+b2;
printf("POINT %.2f %.2f\n", x, y);
}
else if(!f1 && f2)
{
double x = x3;
double y = a1*x+b1;
printf("POINT %.2f %.2f\n", x, y);
}
else if(!f1 && !f2 && fabs(a1-a2) < eps && fabs(b1-b2) < eps) puts("LINE");
else if(!f1 && !f2 && fabs(a1-a2) < eps && b1 != b2) puts("NONE");
else {
double x = (b2-b1)*1.0/(a1-a2);
double y = a1*x + b1;
printf("POINT %.2f %.2f\n", x, y);
}
}
puts("END OF OUTPUT");
return 0;
}
问题虫洞——F: F - Pick-up sticks
黑洞内窥:
有n条木棍,编号为1~n,按顺序给出木棍的位置,
木棍之间相交则必有一条木棍在上面,求顶部木棍的编号。
思维光年:
把木棍想成线段,求n条线段相交,即线段交
ACcode:
//#include<bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include<algorithm>
//#include <map>
//#include <set>
//#include <vector>
//#include <queue>
//#include <stack>
#include <stdlib.h>
#include <cstring>
#include <string.h>
#include <string>
#include <math.h>
using namespace std;
typedef long long ll;
#define MAXN 100005
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll
struct point
{
double x,y;
};
struct line
{
point p1,p2;
} a[100010];
//叉乘
double chacheng(point p1,point p2,point p3)
{
return (p1.x-p3.x)*(p2.y-p3.y)-(p1.y-p3.y)*(p2.x-p3.x);
}
//判断是否相交
int judge(line l1,line l2)
{
if( min(l2.p1.x,l2.p2.x)<=max(l1.p1.x,l1.p2.x)
&& min(l2.p1.y,l2.p2.y)<=max(l1.p1.y,l1.p2.y)
&& min(l1.p1.x,l1.p2.x)<=max(l2.p1.x,l2.p2.x)
&& min(l1.p1.y,l1.p2.y)<=max(l2.p1.y,l2.p2.y)
&& chacheng(l1.p1,l2.p2,l2.p1)*chacheng(l1.p2,l2.p2,l2.p1)<=0//这里需要等于,因为木棍可能堆叠起来。
&& chacheng(l2.p1,l1.p2,l1.p1)*chacheng(l2.p2,l1.p2,l1.p1)<=0 )
return 1;
else
return 0;
}
bool is[MAXN];
int main()
{
int n;
while(cin >> n && n)
{
memset(is, 0, sizeof(is));
for(int i=0; i<n; ++i)
scanf("%lf %lf %lf %lf", &a[i].p1.x, &a[i].p1.y, &a[i].p2.x, &a[i].p2.y);
for(int i=0; i<n-1; ++i)
for(int j=i+1; j<n; ++j)
if(judge(a[i], a[j]))
{
is[i] = 1;
break;
}
printf("Top sticks: ");
for(int i=0; i<n; ++i)
{
if(!is[i])
{
cout << i+1;
if(i == n-1)
cout << ".\n";
else
cout << ", ";
}
}
}
}
问题虫洞——G: G - Treasure Hunt
黑洞内窥:
一个100*100的矩阵,中间有n条线段切割,每条线段代表一扇长长的门
然后给出一个宝藏的坐标,从矩阵的外面穿过矩阵(矩阵算一层门)到宝藏,
每次只能走一段门的中点,求至少要经过多少扇门才能拿到宝藏。
思维光年:
中点不重要,又不是求最短路,,
我们要求的是破门的个数,直接暴力枚举矩阵的边界到宝藏这条线段与所有门的线段交。
取最小值++就绿了~~~~
ACcode:
//#include<bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include<algorithm>
//#include <map>
//#include <set>
//#include <vector>
//#include <queue>
//#include <stack>
#include <stdlib.h>
#include <cstring>
#include <string.h>
#include <string>
#include <math.h>
using namespace std;
typedef long long ll;
#define MAXN 100005
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll
struct point
{
double x,y;
};
struct line
{
point p1,p2;
} a[50], cf;
double chacheng(point p1,point p2,point p3)
{
return (p1.x-p3.x)*(p2.y-p3.y)-(p1.y-p3.y)*(p2.x-p3.x);
}
int judge(line l1,line l2)//线段ll和线段l2是否相交
{
if( min(l2.p1.x, l2.p2.x)<=max(l1.p1.x, l1.p2.x)
&& min(l2.p1.y, l2.p2.y)<=max(l1.p1.y, l1.p2.y)
&& min(l1.p1.x, l1.p2.x)<=max(l2.p1.x, l2.p2.x)
&& min(l1.p1.y, l1.p2.y)<=max(l2.p1.y, l2.p2.y)
&& chacheng(l1.p1, l2.p2, l2.p1)*chacheng(l1.p2, l2.p2, l2.p1)<0//这里不能相等,否则你会wa到枯的~~~~,,,因为如果门重合了,你就不可能走这扇门了。
&& chacheng(l2.p1, l1.p2, l1.p1)*chacheng(l2.p2, l1.p2, l1.p1)<0)
return 1;
return 0;
}
int main()
{
int n;
cin >> n;
if(n == 0)
puts("Number of doors = 1");
else
{
for(int i=0; i<n; ++i)
scanf("%lf %lf %lf %lf", &a[i].p1.x, &a[i].p1.y, &a[i].p2.x, &a[i].p2.y);
scanf("%lf %lf", &cf.p2.x, &cf.p2.y);
int ans = INF;
for(int i=1; i<=100; ++i)
{
cf.p1.x = 0.0, cf.p1.y = i*1.0;
int tot = 0;
for(int j=0; j<n; ++j)
{
if(judge(cf, a[j]))
tot++;
}
ans = min(ans, tot);
cf.p1.x = 100.0, cf.p1.y = i*1.0;
tot = 0;
for(int j=0; j<n; ++j)
{
if(judge(cf, a[j]))
tot++;
}
ans = min(ans, tot);
cf.p1.x = i*1.0, cf.p1.y = 0.0;
tot = 0;
for(int j=0; j<n; ++j)
{
if(judge(cf, a[j]))
tot++;
}
ans = min(ans, tot);
cf.p1.x = i*1.0, cf.p1.y = 100.0;
tot = 0;
for(int j=0; j<n; ++j)
{
if(judge(cf, a[j]))
tot++;
}
ans = min(ans, tot);
if(ans == 0)
break;
}
cout << "Number of doors = " << ans+1 << '\n';
}
return 0;
}
问题虫洞——H: H - Intersection
黑洞内窥:
输入四个点,前两点确定一条线段,
后两点确定一个矩阵,让你判断矩阵和线段的关系。
若相交输出T,否则输出F
思维光年:
线段和矩阵相交的条件:
1、线段在矩阵内;
2、线段和矩阵的边有交点
ACcode:
//#include<bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include<algorithm>
//#include <map>
//#include <set>
//#include <vector>
//#include <queue>
//#include <stack>
#include <stdlib.h>
#include <cstring>
#include <string.h>
#include <string>
#include <math.h>
using namespace std;
typedef long long ll;
#define MAXN 100005
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll
struct point
{
double x,y;
};
struct line
{
point p1,p2;
} a[5], cf;
double chacheng(point p1,point p2,point p3)
{
return (p1.x-p3.x)*(p2.y-p3.y)-(p1.y-p3.y)*(p2.x-p3.x);
}
int judge(line l1,line l2)//线段ll和线段l2是否相交
{
if( min(l2.p1.x, l2.p2.x)<=max(l1.p1.x, l1.p2.x)
&& min(l2.p1.y, l2.p2.y)<=max(l1.p1.y, l1.p2.y)
&& min(l1.p1.x, l1.p2.x)<=max(l2.p1.x, l2.p2.x)
&& min(l1.p1.y, l1.p2.y)<=max(l2.p1.y, l2.p2.y)
&& chacheng(l1.p1, l2.p2, l2.p1)*chacheng(l1.p2, l2.p2, l2.p1)<=0//判断在同一点的两侧
&& chacheng(l2.p1, l1.p2, l1.p1)*chacheng(l2.p2, l1.p2, l1.p1)<=0)
return 1;
return 0;
}
double xx[2], yy[2];
int main()
{
int t;
cin >> t;
while(t--)
{
memset(a, 0, sizeof(a));
scanf("%lf %lf %lf %lf %lf %lf %lf %lf", &cf.p1.x, &cf.p1.y, &cf.p2.x, &cf.p2.y, &xx[0], &yy[0], &xx[1], &yy[1]);
sort(xx, xx+2); sort(yy, yy+2);//存矩阵的边
a[0].p1.x = xx[0], a[0].p1.y = yy[0];
a[0].p2.x = xx[1], a[0].p2.y = yy[0];
a[1].p1.x = xx[0], a[1].p1.y = yy[0];
a[1].p2.x = xx[0], a[1].p2.y = yy[1];
a[2].p1.x = xx[1], a[2].p1.y = yy[1];
a[2].p2.x = xx[1], a[2].p2.y = yy[0];
a[3].p1.x = xx[1], a[3].p1.y = yy[1];
a[3].p2.x = xx[0], a[3].p2.y = yy[1];
if(xx[0]<=cf.p1.x && cf.p1.x <= xx[1] && xx[0]<=cf.p2.x && cf.p2.x <= xx[1] && yy[0]<=cf.p1.y && cf.p1.y <= yy[1] && yy[0]<=cf.p2.y && cf.p2.y <= yy[1])
puts("T");
else
{
int tot=0;
for(int i=0; i<4; ++i)
if(judge(cf, a[i]))
tot++;
if(tot) puts("T");
else puts("F");
}
}
return 0;
}