http://acm.nyist.net/JudgeOnline/problem.php?pid=83
题目解法主要在于判断两线段是否相交,思路是穷举所有地图四周的点,其中每一个边界上的点和终点构成一个线段, 求出所有线段和墙相交的最少次数就是结果
#include<stdio.h>
struct point
{
double x, y;
};
struct line
{
point a, b;
};
double det(double x1, double y1, double x2, double y2)//计算叉积
{
return x1 * y2 - x2 * y1;
}
double get_dir(point a, point b, point c)//计算向量ac 在向量ab的哪个方向(正数为逆时针,负数为顺时针, 零为同向或者反向)
{
return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);
}
int check_cross(line a, line b)//计算出两条线段是否相交,注意只有确定两条线段的都在对方的两侧,才能确定这两条线段相交
{
double flag1 = get_dir(a.a, a.b, b.a) * get_dir(a.a, a.b, b.b);
int f1 = flag1 > 0 ? 1 : -1;
double flag2 = get_dir(b.a, b.b, a.a) * get_dir(b.a, b.b, a.b);
int f2 = flag2 > 0? 1 : -1;
if(f1 < 0 && f2 < 0)
return -1;
else
return 1;
}
line lines[40];
int axis1[101], axis2[101], axis3[101], axis4[101];
int get_cross_number(point start, point end, int total)//计算相交次数
{
line templine;
templine.a = start;
templine.b = end;
int count = 0;
int i;
for(i = 0; i < total; i++)
{
if(check_cross(templine, lines[i]) - 0 < 1e-6)
count ++;
}
return count;
}
int main()
{
int n;
scanf("%d", &n);
while(n--)
{
int m;
int top1, top2, top3, top4;
top1 = top2 = top3 = top4 = 0;
scanf("%d", &m);
int i;
for(i = 0; i < m; i++)
{
int x1, x2, y1, y2;
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
lines[i].a.x = x1;
lines[i].a.y = y1;
lines[i].b.x = x2;
lines[i].b.y = y2;
}
point end;
scanf("%lf %lf", &end.x, &end.y);
int min = 0x7fffffff;
for(i = 0; i < 101; i++)
{
if(min == 0)
break;
point start;
int res;
start.x = 0;
start.y = i;
res = get_cross_number(start, end, m);
if(res < min)
min = res;
start.x = 100;
start.y = i;
res = get_cross_number(start, end, m);
if(res < min)
min = res;
start.x = i;
start.y = 0;
res = get_cross_number(start, end, m);
if(res < min)
min = res;
start.x = i;
start.y = 100;
res = get_cross_number(start, end, m);
if(res < min)
min = res;
}
printf("%d\n", min + 1);
}
return 0;
}
浙公网安备 33010602011771号