POJ 1066 Treasure Hunt【计算几何】

题目

在这里插入图片描述

思路

直接把整个矩阵的各个边的交点和宝藏点连接求最小交点数。
注意四个顶点也要求。
至于为什么不一定要穿过中点,我会了证明再说。

代码

#include<iostream>
#include<cstdio>
using namespace std;
int n,x[100010],y[100010],ans=1e9;
double bzx,bzy;
bool kspc(double x,double y,double xx,double yy,double xx1,double yy1,double xx2,double yy2)
{
	if(x==xx1&&y==yy1)
	  return 0;
	if(x==xx2&&y==yy2)
	  return 0;
	if(xx==xx1&&yy==yy1)
	  return 0;
	if(xx==xx2&&yy==yy2)
	  return 0;
	//1,3,2
	if(xx1<=max(x,xx)&&xx1>=min(x,xx)&&yy1<=max(y,yy)&&yy1>=min(y,yy)&&(xx-x)*(yy1-y)-(xx1-x)*(yy-y)==0)
	  return 1;
	//3,2,4
	else if(xx<=max(xx1,xx2)&&xx>=min(xx1,xx2)&&yy<=max(yy1,yy2)&&yy>=min(yy1,yy2)&&(xx1-xx)*(yy2-yy)-(xx2-xx)*(yy1-yy)==0)
	  return 1;
	//1,4,2
	else if(xx2<=max(x,xx)&&xx2>=min(x,xx)&&yy2<=max(y,yy)&&yy2>=min(y,yy)&&(xx2-x)*(yy-y)-(xx-x)*(yy2-y)==0)
	  return 1;
	//3,1,4
	else if(x<=max(xx1,xx2)&&x>=min(xx1,xx2)&&y<=max(yy1,yy2)&&y>=min(yy1,yy2)&&(x-xx1)*(yy2-yy1)-(xx2-xx1)*(y-yy1)==0)
	  return 1;
	return 0;
}
bool klsy(double x,double y,double xx,double yy,double xx1,double yy1,double xx2,double yy2)
{
	if(x==xx1&&y==yy1)
	  return 0;
	if(x==xx2&&y==yy2)
	  return 0;
	if(xx==xx1&&yy==yy1)
	  return 0;
	if(xx==xx2&&yy==yy2)
	  return 0;
	if(((xx-x)*(yy1-y)-(xx1-x)*(yy-y))*((xx-x)*(yy2-y)-(xx2-x)*(yy-y))<0)
	 if(((x-xx1)*(yy2-yy1)-(xx2-xx1)*(y-yy1))*((xx-xx1)*(yy2-yy1)-(xx2-xx1)*(yy-yy1))<0)
       return 1;
    return 0;
}
int main()
{
	scanf("%d",&n);
	for(int i=1; i<=n; i++)
	   scanf("%d%d%d%d",&x[i],&y[i],&x[i+n],&y[i+n]);
	scanf("%lf%lf",&bzx,&bzy);
	for(int i=1; i<=2*n; i++)
	 {
	 	int xx=x[i],yy=y[i],js=0;
	 	for(int j=1; j<=n; j++)
	 	 {
	 	 	if((klsy(bzx,bzy,xx,yy,x[j],y[j],x[j+n],y[j+n])||kspc(bzx,bzy,xx,yy,x[j],y[j],x[j+n],y[j+n]))==1)
	 	 	  js++;
		 }
		ans=min(ans,js);
	 }
	int xx=0,yy=0,js=0;
	for(int j=1; j<=n; j++)
	 {
	 	if((klsy(bzx,bzy,xx,yy,x[j],y[j],x[j+n],y[j+n])||kspc(bzx,bzy,xx,yy,x[j],y[j],x[j+n],y[j+n]))==1)
	 	  js++;
	 }
	ans=min(ans,js);
	xx=0,yy=100,js=0;
	for(int j=1; j<=n; j++)
	 {
	 	if((klsy(bzx,bzy,xx,yy,x[j],y[j],x[j+n],y[j+n])||kspc(bzx,bzy,xx,yy,x[j],y[j],x[j+n],y[j+n]))==1)
	 	  js++;
	 }
	ans=min(ans,js);
	xx=100,yy=0,js=0;
	for(int j=1; j<=n; j++)
	 {
	 	if((klsy(bzx,bzy,xx,yy,x[j],y[j],x[j+n],y[j+n])||kspc(bzx,bzy,xx,yy,x[j],y[j],x[j+n],y[j+n]))==1)
	 	  js++;
	 }
	ans=min(ans,js);
	xx=100,yy=100,js=0;
	for(int j=1; j<=n; j++)
	 {
	 	if((klsy(bzx,bzy,xx,yy,x[j],y[j],x[j+n],y[j+n])||kspc(bzx,bzy,xx,yy,x[j],y[j],x[j+n],y[j+n]))==1)
	 	  js++;
	 }
	ans=min(ans,js);
	printf("Number of doors = %d",ans+1);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值