题意:
题目链接
快捷版题意:一个正方形格子中有若干隔板,问从指定位置走出正方形格子至少穿过多少隔板(边界也算;不能穿交点)
思路:
开始时百思不得其解,想要给分割出来的每个小格子编号,然后连边跑最短路
但是怎么编号?怎么连边?比较困难。
发现其实不一定非要按着题目的规则(即走每段墙的中点),可以等效成一条直线
只关心终点,枚举,然后与起点连接,枚举每条边,累计交点个数
至于如何枚举终点,发现每一段可以等效为其端点。枚举端点即可。
注意事项:
判断交点时要(<0,)不能(<=0)
code:
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
const int N=50;
int t,n,ans;
struct point{double x,y;}st;
point operator-(point x,point y){return (point){x.x-y.x,x.y-y.y};}
double operator^(point x,point y){return x.x*y.y-x.y*y.x;}
struct edge{point p1,p2;}e[N];
inline int read()
{
int s=0,w=1; char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
for(;isdigit(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
return s*w;
}
inline int ck(point pt)
{
int ret=0;
for(int i=1;i<=n;++i)
{
point u=e[i].p1,v=e[i].p2;
ret+=((((u-st)^(v-st))*((u-pt)^(v-pt)))<0)&((((st-u)^(pt-u))*((st-v)^(pt-v)))<0);
}
return ret+1;
}
int main()
{
t=1;
while(t--)
{
n=read();ans=1e9;
if(!n){puts("Number of doors = 1");if(t)puts("");continue;}
for(int i=1;i<=n;++i)
{
e[i].p1=(point){read(),read()};
e[i].p2=(point){read(),read()};
}
scanf("%lf%lf",&st.x,&st.y);
for(int i=1;i<=n;++i)
{
ans=min(ans,ck(e[i].p1));
ans=min(ans,ck(e[i].p2));
}
printf("Number of doors = %d
",ans);
if(t) puts("");
}
return 0;
}