POJ1066向量叉乘法解题报告

版权声明:仅供研究,转载请注明出处。 https://blog.csdn.net/CSUstudent007/article/details/83447717

首先你要知道如何判断两条线段相交:https://blog.csdn.net/qq826309057/article/details/70942061

 思路:

枚举外墙上每道内墙的两个端点和p(宝物)的连线这条线段和内墙的交点的次数最小值即为需要炸墙的最小次数

#include<iostream>
#include<cstdio>
#include<cmath>
#define eps 1e-6
using namespace std;
struct point{
	double x,y;
};
struct Line{
	struct point a,b;
}lines[35];
bool intersection(const Line &l1,const Line &l2){
	//快速排斥
	if(max(l2.a.x,l2.b.x)<min(l1.a.x,l1.b.x)||max(l2.a.y,l2.b.y)<min(l1.a.y,l1.b.y)||max(l1.a.x,l1.b.x)<min(l2.a.x,l2.b.x)||max(l1.a.y,l1.b.y)<min(l2.a.y,l2.b.y))
		return false;
	//跨立实验
	double ad_cd=(l1.a.x-l2.b.x)*(l2.a.y-l2.b.y)-(l1.a.y-l2.b.y)*(l2.a.x-l2.b.x);
	double bd_cd=(l1.b.x-l2.b.x)*(l2.a.y-l2.b.y)-(l1.b.y-l2.b.y)*(l2.a.x-l2.b.x);
	double ac_ab=(l2.a.x-l1.a.x)*(l1.b.y-l1.a.y)-(l2.a.y-l1.a.y)*(l1.b.x-l1.a.x);
	double ad_ab=(l2.b.x-l1.a.x)*(l1.b.y-l1.a.y)-(l2.b.y-l1.a.y)*(l1.b.x-l1.a.x);
	return ad_cd*bd_cd<=eps&&ac_ab*ad_ab<=eps;	 
}
int main(){
	int n,mmin=100,cnt;
	double topx,topy;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%lf%lf%lf%lf",&lines[i].a.x,&lines[i].a.y,&lines[i].b.x,&lines[i].b.y);
	}
	scanf("%lf%lf",&topx,&topy);
	if(n==0){
		cnt=1;
		printf("Number of doors = %d\n",cnt);
		return 0;
	}
	for(int i=0;i<n;i++){
		lines[n].a.x=topx;lines[n].a.y=topy;//a端为宝物所在的终点 
		lines[n].b.x=lines[i].a.x;lines[n].b.y=lines[i].a.y;//b端为外墙上的内墙的端点
		cnt=0;
		for(int j=0;j<n;j++)
			if(intersection(lines[n],lines[j])) cnt++;
		mmin=min(mmin,cnt);
		lines[n].b.x=lines[i].b.x,lines[n].b.y=lines[i].b.y;
		cnt=0;
		for(int j=0;j<n;j++)
			if(intersection(lines[n],lines[j])) cnt++;
		mmin=min(mmin,cnt); 
	}
	printf("Number of doors = %d\n",mmin);
	return 0; 
} 

猜你喜欢

转载自blog.csdn.net/CSUstudent007/article/details/83447717