POJ-1066 Treasure Hunt

题意:给出一些直线,直线与直线切割的线段是围墙,只能从围墙中间穿过,问最少穿过几层墙才能到达终点

看到数据范围很小就开心地写了暴力找点+最短路,后来看了hzwer大神的题解才发现我还是太naive了...

这道题只要求从终点到外围直线与围墙的最少交点就能过!

#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e3+100,maxm=1e6+100;
struct Point{
	double x,y;
	Point(double xx=0,double yy=0){
		x=xx,y=yy;
	}
}b[maxn],a[maxn],s[maxn],t[maxn],zhy,sa[4],ta[4];
struct Vector{
	double x,y;
	Vector(double xx=0,double yy=0){
		x=xx,y=yy;
	}
};
struct node{
	int poi,bh;
}nh;
int n,m,v[maxm],w[maxm],nex[maxm],head[maxn],num,bj[maxn];
int dcmp(double x){return fabs(x)<1e-9?0:(x>0?1:-1);}
Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
Point operator + (Point a,Vector b){return Point(a.x+b.x,a.y+b.y);}
Vector operator * (double p,Vector a){return Vector(a.x*p,a.y*p);}
bool operator < (Point a,Point b){return dcmp(a.x-b.x)==0?(dcmp(a.y-b.y)<0):(dcmp(a.x-b.x)<0);}
bool operator < (node a,node b){return a.poi>b.poi;}
double operator * (Vector a,Vector b){return a.x*b.y-a.y*b.x;}
Point glt(Point a,Point b,Point c,Point d){
	Vector v1=b-a,v2=d-c,v3=a-c;
	return a+v2*v3/(v1*v2)*v1;
}
priority_queue<node>q;
void add(int x,int y){
	v[++num]=y;
	w[num]=1;
	nex[num]=head[x];
	head[x]=num;
	v[++num]=x;
	w[num]=1;
	nex[num]=head[y];
	head[y]=num;
}
bool segment(Point a,Point b,Point c,Point d,int ms=0){
	Vector x=b-a,y=d-c;
	Vector v1=c-a,v2=d-a;
	if(ms&&dcmp(x*v1)*dcmp(x*v2)>0) return 0;
	if(!ms&&dcmp(x*v1)*dcmp(x*v2)>=0) return 0;
	v1=a-c,v2=b-c;
	if(ms&&dcmp(y*v1)*dcmp(y*v2)>0) return 0;
	if(!ms&&dcmp(y*v2)*dcmp(y*v1)>=0) return 0;
	return 1;
}
void getdist(){
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++){
			bool ok=1;
			for(int k=1;k<=m;k++)
				if(segment(b[i],b[j],s[k],t[k])){
					ok=0;
					break;
				}
			if(ok&&j==n)
				ok=1;
			if(ok) add(i,j);
		}
}
void dij(){
	memset(bj,0x3f,sizeof(bj));
	bj[0]=0;
	nh.bh=0,nh.poi=0;
	q.push(nh);
	while(!q.empty()){
		node now=q.top();
		q.pop();
		int x=now.bh,z=now.poi;
		if(z>bj[x]) continue;
		for(int i=head[x];i;i=nex[i])
			if(bj[v[i]]>bj[x]+w[i]){
				bj[v[i]]=bj[x]+w[i];
				nh.bh=v[i],nh.poi=bj[v[i]];
				q.push(nh);
			}
	}
	printf("Number of doors = %d
",bj[n]-1);
}
int main(){
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
		scanf("%lf%lf%lf%lf",&s[i].x,&s[i].y,&t[i].x,&t[i].y);
	sa[0]=Point(0,0),ta[0]=Point(0,100);
	sa[1]=Point(0,0),ta[1]=Point(100,0);
	sa[2]=Point(100,100),ta[2]=Point(0,100);
	sa[3]=Point(100,100),ta[3]=Point(100,0);
	for(int i=1;i<=m;i++){
		num=0;
		for(int j=1;j<=m;j++)
			if(i!=j&&segment(s[i],t[i],s[j],t[j]))
				a[++num]=glt(s[i],t[i],s[j],t[j]);
		for(int j=0;j<4;j++)
			if(segment(s[i],t[i],sa[j],ta[j],1))
				a[++num]=glt(s[i],t[i],sa[j],ta[j]);
		sort(a+1,a+num+1);
		for(int i=1;i<num;i++)
			b[++n]=Point((a[i].x+a[i+1].x)/2,(a[i].y+a[i+1].y)/2);
	}
	int k=n+1;
	for(int i=0;i<4;i++){
		num=0;
		for(int j=1;j<=m;j++)
			if(segment(sa[i],ta[i],s[j],t[j],1))
				a[++num]=glt(sa[i],ta[i],s[j],t[j]);
		for(int j=0;j<4;j++)
			if(i!=j&&segment(sa[i],ta[i],sa[j],ta[j],1))
				a[++num]=glt(sa[i],ta[i],sa[j],ta[j]);
		sort(a+1,a+num+1);
		for(int i=1;i<num;i++)
			b[++n]=Point((a[i].x+a[i+1].x)/2,(a[i].y+a[i+1].y)/2);
	}
	num=1;
	for(;k<=n;k++) add(0,k);
	scanf("%lf%lf",&zhy.x,&zhy.y);
	b[++n]=zhy;
	getdist();
	dij();
	return 0;
}
原文地址:https://www.cnblogs.com/nianheng/p/10010115.html