Treasure Hunt

题意:

题目链接
快捷版题意:一个正方形格子中有若干隔板,问从指定位置走出正方形格子至少穿过多少隔板(边界也算;不能穿交点)

思路:

开始时百思不得其解,想要给分割出来的每个小格子编号,然后连边跑最短路
但是怎么编号?怎么连边?比较困难。
发现其实不一定非要按着题目的规则(即走每段墙的中点),可以等效成一条直线
只关心终点,枚举,然后与起点连接,枚举每条边,累计交点个数
至于如何枚举终点,发现每一段可以等效为其端点。枚举端点即可。

注意事项:

判断交点时要\(<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\n",ans);
		if(t) puts("");
	}
	return 0;
}
posted @ 2020-01-19 15:54  BILL666  阅读(306)  评论(0编辑  收藏  举报