poj 2074 Line of Sight
这个题就是求无论你站在家的那个地方都能看到财产的最大值;
这个题可以从正面做,直接用叉积求出最大值;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; class Line { public: double x1,x2,y; }line[10000]; Line house,pro; int dcmp( double x ) { if( fabs( x ) < 1.0e-12 ) return 0; if( x < 0 ) return -1; return 1; } bool cmp( Line a, Line b ) { if( a.x1 < b.x1 ) return true; else if( dcmp( a.x1 - b.x1)==0 && a.y < b.y ) return true; return false; } double multi( double x1,double y1 ,double x2 ,double y2 ) { return x1*y2 - x2*y1; } double segment( double x1,double y1 ,double x2,double y2, Line L ) { int d1 = dcmp(multi( x1 - L.x1 , y1 - L.y ,x2 -L.x1 ,y2 - L.y )); int d2 = dcmp(multi( x1 - L.x2 , y1 - L.y ,x2 -L.x2 ,y2 - L.y )); return d1*d2; } int view_right( int t ,int n) { for( int i = 0 ; i < n ; i ++) { if( segment(house.x1 ,house.y , line[t].x2,line[t].y,line[i] ) < 0 ) return i; } return t; } int view_left( int t ,int n ) { for( int i = 0 ; i < n ; i ++) { if( segment(house.x2 ,house.y , line[t].x1,line[t].y,line[i] )< 0 ) return i; } return t; } double Max( double a , double b) { return a > b ? a : b; } double Solve( int n ) { double ans = 0,A1,B1,A2,B2; int t = view_left( 0 , n ),tt=0; while( t != tt ) { // printf( "%d\n",t ); // getchar(); tt = t; t = view_left( t , n ); } A1 = house.x2 - line[t].x1;B1 = house.y - line[t].y; ans = Max( ans , ( pro.y - house.y )*A1/B1 + house.x2 - pro.x1 ); tt = t = n-1; t = view_right( t , n ); while( t != tt ) { tt = t; t = view_right( t , n ); } A1 = house.x1 - line[t].x2;B1 = house.y - line[t].y; ans = Max( ans , pro.x2 - ( ( pro.y - house.y )*A1/B1 + house.x1 ) ); int i = 0; while( i < n ) { tt = t = i; t = view_right( t , n ); while( tt != t ) { tt = t; t = view_right( t , n ); } A1 = house.x1 - line[t].x2;B1 = house.y - line[t].y; int j = 0; while( line[j].x1 < line[t].x2 && j < n ) j++; if( j == n ) break; tt = t = j; t = view_left( t , n ); while( tt!=t ) { tt = t; t = view_left( t , n ); } A2 = house.x2 - line[t].x1;B2 = house.y - line[t].y; double x1 = ( pro.y - house.y )*A1/B1 + house.x1; double x2 = ( pro.y - house.y )*A2/B2 + house.x2 ; ans = Max( ans , x2 - x1 ); i = t; } return ans; } int main( ) { while( scanf( "%lf %lf %lf",&house.x1,&house.x2,&house.y )==3) { int n,flag = 0,cnt=0; if(dcmp(house.x1)==0&&dcmp(house.x2)==0&&dcmp(house.y)==0 ) break; scanf( "%lf %lf %lf",&pro.x1, &pro.x2,&pro.y ); scanf( "%d",&n ); for( int i = 0; i < n ; i++ ) { scanf( "%lf %lf %lf",&line[i].x1,&line[i].x2,&line[i].y ); if( dcmp(line[i].y - house.y) ==0 ) { if( dcmp( line[i].x1 - house.x2 ) <= 0 && dcmp( line[i].x2 - house.x1 ) >= 0 ) flag = 1; } else if( line[i].y < house.y && line[i].y > pro.y )line[cnt++] = line[i]; } if( flag ) printf( "No View\n" ); else { if( cnt == 0 ) printf( "%.2f\n",pro.x2-pro.x1 ); else { sort( line , line + cnt , cmp ); double view = Solve( cnt ); if( dcmp( view )==0 ) printf( "No View\n" ); else printf( "%.2f\n",view ); } } } //system( "pause" ); return 0; }
从反面,就是求出他看不到的地方,再线性遍历求出最大值;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; class Line { public: double x1,x2,y; }line[224]; Line house,pro; int dcmp( double x ) { if( fabs( x ) < 1.0e-12 ) return 0; if( x < 0 ) return -1; return 1; } bool cmp( Line a, Line b ) { if( a.x1 < b.x1 ) return true; else if( dcmp( a.x1 - b.x1)==0 && a.y < b.y ) return true; return false; } double Max( double a , double b) { return a > b ? a : b; } double Solve( int n ) { Line L[224]={0}; double A1,B,A2; for( int i = 0 ; i < n ; i ++ ) { A1 = house.x2 - line[i].x1; B = house.y - line[i].y; A2 = house.x1 - line[i].x2; L[i].x1 = ( pro.y - house.y )*A1/B + house.x2; L[i].x2 = ( pro.y - house.y )*A2/B + house.x1; } sort( L , L + n , cmp ); double ans = 0; if( L[0].x1 > pro.x1 ) ans = L[0].x1 - pro.x1; double t = L[0].x2; for( int i = 1 ; i < n ; i ++ ) { if( L[i].x1 <= t ) t = Max( t , L[i].x2 ); else { ans = Max( ans , L[i].x1 - t ); t = L[i].x2; } } ans = Max( ans , pro.x2 - t ); return ans; } int main( ) { while( scanf( "%lf %lf %lf",&house.x1,&house.x2,&house.y )==3) { int n,flag = 0,cnt=0; if(dcmp(house.x1)==0&&dcmp(house.x2)==0&&dcmp(house.y)==0 ) break; scanf( "%lf %lf %lf",&pro.x1, &pro.x2,&pro.y ); scanf( "%d",&n ); for( int i = 0; i < n ; i++ ) { scanf( "%lf %lf %lf",&line[i].x1,&line[i].x2,&line[i].y ); if( dcmp(line[i].y - house.y) ==0 ) { if( dcmp( line[i].x1 - house.x2 ) <= 0 && dcmp( line[i].x2 - house.x1 ) >= 0 ) flag = 1; } else if( line[i].y < house.y && line[i].y > pro.y )line[cnt++] = line[i]; } if( flag ) printf( "No View\n" ); else { if( cnt == 0 ) printf( "%.2f\n",pro.x2-pro.x1 ); else { sort( line , line + cnt , cmp ); double view = Solve( cnt ); if( dcmp( view )==0 ) printf( "No View\n" ); else printf( "%.2f\n",view ); } } } //system( "pause" ); return 0; }