题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=83
题目分析:
好吧,我承认这个题折腾了我接近两个小时~~
其实这道题就是任选一个四周墙壁上的点,然后与目标点连成一个线段,然后求该线段与所给的所有线段的交点数。取最少的交点数。
不过这道题很坑爹啊,要求输入的点的坐标是整数,结构后来目标点的坐标却不一定是整数,为什么不全部要求是浮点数呢?只要有一个是整数,定义的结构体就要是整数啊~~而且题目叙述中给的输入顺序是x1,x2,y1,y2,我还纳闷为什么这个顺序跟常规思维有点不一样,结果测试一下,错了。然后结合它给的图和数据一看,我知道被坑了,其实顺序应该是x1,y1,x2,y2的,偶只好赶紧把顺序改过来,这就对了。
参考代码:
#include<stdio.h>
#include<math.h>
typedef struct
{
double x;
double y;
}POINT;
typedef struct
{
POINT p1;
POINT p2;
}LINE;
inline double CrossProduct(POINT *p1, POINT *p2, POINT *p3)
{
return (p2->x - p1->x) * (p2->y - p3->y) - (p2->x - p3->x) * (p2->y - p1->y);
}
inline double min(const double a, const double b)
{
return a < b ? a : b;
}
inline double max(const double a, const double b)
{
return a > b ? a : b;
}
inline bool InSegment(POINT *p, LINE *l)
{//判断点是否在线段中
if(p->x >= min(l->p1.x, l->p2.x) && p->x <= max(l->p1.x, l->p2.x)
&& p->y >= min(l->p1.y, l->p2.y) && p->y <= max(l->p1.y, l->p2.y))
return true;
else
return false;
}
bool SegmentIntersect(LINE *l1, LINE *l2)
{//判断两个线段是否相交,第一个是判断是否相交,后面四个if是判断其中一个线段是否包含了另一个线段的端点
double d1 = CrossProduct(&l1->p1, &l1->p2, &l2->p1);
double d2 = CrossProduct(&l1->p1, &l1->p2, &l2->p2);
double d3 = CrossProduct(&l2->p1, &l2->p2, &l1->p1);
double d4 = CrossProduct(&l2->p1, &l2->p2, &l1->p2);
if( ((d1 < 0 && d2 > 0) || (d1 > 0 && d2 < 0)) &&
((d3 < 0 && d4 > 0) || (d3 > 0 && d4 < 0)))
return true;
else if(fabs(d1) < 0.0000001 && InSegment(&l2->p1, l1))
return true;
else if(fabs(d2) < 0.0000001 && InSegment(&l2->p2, l1))
return true;
else if(fabs(d3) < 0.0000001 && InSegment(&l1->p1, l2))
return true;
else if(fabs(d4) < 0.0000001 && InSegment(&l1->p2, l2))
return true;
else
return false;
}
int GetIntersect(LINE *l, int n, POINT *p)
{//求交点数
int i,j;
int ans,count;
ans = 35;
LINE line;
line.p2 = *p;
//左
line.p1.x = 0.0;
for(i = 1; i < 100; ++i)
{
line.p1.y = i;
count = 0;
for(j = 0; j < n; ++j)
{
if((fabs(l[j].p1.x) < 0.0000001 && l[j].p1.y == i) ||
(fabs(l[j].p2.x) < 0.0000001 && l[j].p2.y == i))
continue;
if(SegmentIntersect(&line,&l[j]))
++count;
}
ans = min(ans, count);
}
//右
line.p1.x = 100;
for(i = 1; i < 100; ++i)
{
line.p1.y = i;
count = 0;
for(j = 0; j < n; ++j)
{
if((l[j].p1.x == 100.0 && l[j].p1.y == i) ||
(l[j].p2.x == 100.0 && l[j].p2.y == i))
continue;
if(SegmentIntersect(&line,&l[j]))
++count;
}
ans = min(ans, count);
}
//下
line.p1.y = 0.0;
for(i = 1; i < 100; ++i)
{
line.p1.x = i;
count = 0;
for(j = 0; j < n; ++j)
{
if((fabs(l[j].p1.y) < 0.0000001 && l[j].p1.x == i) ||
(fabs(l[j].p2.y) < 0.0000001 && l[j].p2.x == i))
continue;
if(SegmentIntersect(&line,&l[j]))
++count;
}
ans = min(ans, count);
}
//左
line.p1.y = 100;
for(i = 1; i < 100; ++i)
{
line.p1.x = i;
count = 0;
for(j = 0; j < n; ++j)
{
if((l[j].p1.y == 100.0 && l[j].p1.x == i) ||
(l[j].p2.y == 100.0 && l[j].p2.x == i))
continue;
if(SegmentIntersect(&line,&l[j]))
++count;
}
ans = min(ans, count);
}
return ans;
}
int main()
{
int n,t;
int i,ans;
LINE line[35];
POINT p;
scanf("%d",&t);
//左
line[0].p1.x = 0;
line[0].p1.y = 0;
line[0].p2.x = 0;
line[0].p2.y = 100;
//右
line[1].p1.x = 100;
line[1].p1.y = 0;
line[1].p2.x = 100;
line[1].p2.y = 100;
//下
line[2].p1.x = 0;
line[2].p1.y = 0;
line[2].p2.x = 100;
line[2].p2.y = 0;
//上
line[3].p1.x = 0;
line[3].p1.y = 100;
line[3].p2.x = 100;
line[3].p2.y = 100;
while(t--)
{
scanf("%d",&n);
n += 4;
for(i = 4; i < n; ++i)
scanf("%lf %lf %lf %lf", &line[i].p1.x, &line[i].p1.y, &line[i].p2.x, &line[i].p2.y);
scanf("%lf %lf", &p.x, &p.y);
ans = GetIntersect(line, n, &p);
printf("%d\n",ans);
}
}