[U]3.4.1 蛋疼的计算几何,二分

采用二分的方法,查找是否可见对面的篱笆。左边,右边两方收缩,采用点积叉积判断是否相交。

代码很丑.... 无视...

/*
ID:bysen
LANG:C++
PROG:fence4
*/
#include<stdio.h>
#include<algorithm>
#include<cmath>
#define MAXP 201
#define ERROR 1e-6
using namespace std;

struct Point
{
 	   double x,y;
}point[MAXP],stand;

struct Line
{
 	   double x1,x2,y1,y2;
 	   int d1,d2;
}line[MAXP];

int pointnum;
int linenum;
int sign(double);
double xmult( Point,Point);
bool cross(Point,Point,Point,Point);
bool cross1(Point,Point,Point,Point);
bool cross(Point,Point,int);
void init();
bool legal();
void binarySeach();
void print();
int min( int a,int b ){ return a<b?a:b; }
int max( int a,int b ){ return a>b?a:b; }
bool cmp( Line a,Line b )
{
 	 if( a.d2==b.d2 )
 	 	 return a.d1<b.d1;
 	 return a.d2<b.d2;
}

int main()
{
 	freopen( "fence4.in","r",stdin );
 	freopen( "fence4.out","w",stdout );
 	init();
 	if( !legal() ){
	 	printf( "NOFENCE\n" );
		return 0;
    }
    binarySeach();
    sort( line,line+linenum,cmp );
	print();
 	return 0;
}

void print()
{
 	 printf( "%d\n",linenum );
 	 for( int i=0;i<linenum;i++ )
 	 	  printf( "%d %d %d %d\n",(int)line[i].x1,(int)line[i].y1,(int)line[i].x2,(int)line[i].y2 );
}

void binarySeach()
{
 	 linenum=0;
 	 for( int i=0;i<pointnum;i++ )//judge [i,i+1] line
 	 {
	  	  Point l=point[i];
	  	  Point r=point[(i+1)%pointnum];
	  	  Point m;
	  	  while(true)//夹逼 
	  	  {
 				 if( fabs(r.x-l.x)<ERROR && fabs(r.y-l.y)<ERROR )
		   		 	 break;
		   		 m.x=(l.x+r.x)/2;
	  	  		 m.y=(l.y+r.y)/2;
	 	  		 if( !cross(stand,m,i) )
	 	  		 {
				  	 if( (fabs(m.x-l.x)<ERROR&&fabs(m.y-l.y)<ERROR) || (fabs(m.x-r.x)<ERROR&&fabs(m.y-r.y)<ERROR) )
	 				 	  break;
					 line[linenum].x1=point[min(i,(i+1)%pointnum)].x;
		   	  		 line[linenum].x2=point[max(i,(i+1)%pointnum)].x;
		   	  		 line[linenum].y1=point[min(i,(i+1)%pointnum)].y;
		   	  		 line[linenum].y2=point[max(i,(i+1)%pointnum)].y;
		   	  		 line[linenum].d1=min(i,(i+1)%pointnum);
		   	  		 line[linenum].d2=max(i,(i+1)%pointnum);
		   	  		 linenum++;
		   	  		 break;
	  	  		 }
	  	  		 if( cross(stand,l,i) )
	  	  		 {
				  	 l.x=(l.x+m.x)/2;
				  	 l.y=(l.y+m.y)/2;
				 }
				 if( cross(stand,r,(i+1)%pointnum) )
				 {
				  	 r.x=(r.x+m.x)/2;
				  	 r.y=(r.y+m.y)/2;
	  	 		 }
   		  }
	 }
}


void init()
{
 	scanf( "%d",&pointnum );
 	scanf( "%lf %lf",&stand.x,&stand.y );
 	for( int i=0;i<pointnum;i++ )
 		 scanf( "%lf %lf",&point[i].x,&point[i].y );
}

bool legal()
{
 	 for( int i=0;i<pointnum;i++ )//use i and i+1 line
 	 for( int j=0;j<pointnum;j++ )//to cross [j,j+1]line
 	 	  if( cross( point[i],point[(i+1)%pointnum],point[j],point[(j+1)%pointnum] ) )
 	 	  	  return false;
	 return true;
}

int sign( double a )
{
 	   if( fabs(a)<ERROR )
 	   	   return 0;
 	   return a>0?1:-1;
}

double xmult( Point p,Point q ){ return p.x*q.y-p.y*q.x; }

bool cross( Point a,Point b,Point c,Point d )
{
 	 Point AB,CB,DB,CD,AD,BD;
 	 AB.x=a.x-b.x;AB.y=a.y-b.y;
 	 CB.x=c.x-b.x;CB.y=c.y-b.y;
 	 DB.x=d.x-b.x;DB.y=d.y-b.y;
 	 
 	 CD.x=c.x-d.x;CD.y=c.y-d.y;
 	 AD.x=a.x-d.x;AD.y=a.y-d.y;
 	 BD.x=b.x-d.x;BD.y=b.y-d.y;
 	 
 	 if( sign(xmult(AB,CB))*sign(xmult(AB,DB))<0 && sign(xmult(CD,AD))*sign(xmult(CD,BD))<0 )
 	 	 return true;
 	 return false;
}

bool cross1( Point a,Point b,Point c,Point d )
{
 	 Point AB,CB,DB,CD,AD,BD;
 	 AB.x=a.x-b.x;AB.y=a.y-b.y;
 	 CB.x=c.x-b.x;CB.y=c.y-b.y;
 	 DB.x=d.x-b.x;DB.y=d.y-b.y;
 	 
 	 CD.x=c.x-d.x;CD.y=c.y-d.y;
 	 AD.x=a.x-d.x;AD.y=a.y-d.y;
 	 BD.x=b.x-d.x;BD.y=b.y-d.y;
 	 
 	 if( sign(xmult(AB,CB))*sign(xmult(AB,DB))<=0 && sign(xmult(CD,AD))*sign(xmult(CD,BD))<0 )
 	 	 return true;
 	 return false;
}

bool cross( Point a,Point b,int at)
{
 	 //a,b 不是边上的点, 
 	 for( int i=0;i<pointnum;i++ )
 	 {
 	 	  if( at==i )
 	 	  	  continue;
 	 	  if( cross1(a,b,point[i],point[(i+1)%pointnum])==true )
 	 	  	  return true;
	 }
	 return false;
}


你可能感兴趣的:(c)