我刚开始被这道题目的名字吸引了,因为它和宝藏有关,呵呵^_^不过把题目读完以后才发现这道题是个无聊的计算几何题 ,说实话有点失望。。。
题目的大意是这样的:寻宝者在一个被分割成很多房间的正方形迷宫里寻宝,这个迷宫是100*100的正方形而且四个顶点坐标一定。寻宝者具有把墙凿穿通过的能力,若寻宝者可以从正方形的任意一个边界进入,问到达藏宝地点最少要穿过几道墙?
这个题的解法是:枚举每一个入口。然后在所有的情况中取穿墙数最少的输出即可。
考察每一个入口的时候,枚举每条边,如果起点和终点在这条直线的两侧,那么寻宝者一定要穿过一道墙。于是此题转化成了判断2点是否在一条直线的异侧的问题。模板解决~
由于自己写的有点冗长,于是参考了下网上的代码,发现将所有边界上的点按照角度排序的确是个很巧妙的方法,学习了^_^
//coded by abilitytao
//Time:2009年8月5日17:50:19
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
double const EPS = 1e-8;
const int INF = 0xf777777;
#define zero(x) (((x)>0?(x):-(x))<eps)
struct Point
{
double x,y;
Point(){}
Point(double a, double b):x(a), y(b){}
bool operator<(Point a){return atan2(y - 50, x - 50) < atan2(a.y - 50, a.x - 50); }
};
struct Line// 定义一条线段,用起点和终点来表示
{
Point a, b;
Line() {}
Line(Point p10, Point p20): a(p10), b(p20) {} //Line a(p1,p2);
};
Point mypoint[64], s, t;
Line myline[30];
int n, countnum, minnum;
double xmult(Point p1, Point p2 , Point p0)
{
return (p1.x - p0.x)*(p2.y - p0.y)-(p2.x - p0.x)*(p1.y - p0.y);
}
int same_side(Point p1,Point p2,Line l)
{
return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)>EPS;
}
int main()
{
int i, j, ans;
minnum = INF; countnum = 0;
mypoint[countnum++] = Point(0, 0);
mypoint[countnum++] = Point(100, 0);
mypoint[countnum++] = Point(0, 100);
mypoint[countnum++] = Point(100, 100);
cin >> n;
for(i = 0; i < n; i++)
{
scanf("%lf%lf%lf%lf",&myline[i].a.x ,&myline[i].a.y ,&myline[i].b.x ,&myline[i].b.y);
mypoint[countnum++] = myline[i].a;
mypoint[countnum++] = myline[i].b;
}
scanf("%lf%lf",&s.x,&s.y);
sort(mypoint, mypoint+countnum);
for(i=0;i<countnum;i++ )
{
ans = 0;
t = Point( (mypoint[i].x + mypoint[(i+1)%countnum].x)/2, (mypoint[i].y + mypoint[(i+1)%countnum].y)/2 );
for(j = 0; j < n; j++)
if(!same_side(s, t, myline[j]))
ans++;
if(ans <minnum) minnum = ans;
}
printf("Number of doors = %d\n", minnum+1);
return 0;
}