给一个有很多隔栏的箱子以及一些玩具的坐标,求箱子每个区域内玩具个数。
其实就是二分+叉积判断。
通过二分隔栏线段,得到一个玩具所在区域。
玩具(x,y)所在区域的判断方式是与左边隔栏叉积小于0,右边大于0.
第一次真正意义上做计算几何的题,对叉积理解还不够充分,连WA好多发,啊。。
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const double eps(1e-6) ;
const int maxn = 5050 ;
struct Point{
int x , y ;
Point( int x = 0 , int y = 0 ) : x(x) , y(y){} ;
} ;
typedef Point Vector ;
int det( Vector a , Vector b ){
return a.x * b.y - a.y * b.x ;
}
int u[maxn] , l[maxn] ;
int cnt[maxn] ;
int main(){
//freopen("input.txt","r",stdin);
int n , m ;
int x1 , y1 , x2 , y2 ;
while( cin >> n >> m >> x1 >> y1 >> x2 >> y2 && n ){
cls( cnt ) ; cls( u ) ; cls( l ) ;
for( int i = 0 ; i < n ; i++ ){
scanf( "%d%d" , u+i , l+i ) ;
}
u[n] = l[n] = x2 ;
for( int i = 0 ; i < m ; i++ ){
int X , Y ;
scanf( "%d%d" , &X , &Y ) ;
int pos ;
int L = 0 , R = n ;
while( L <= R ){
int M = ( L + R ) >> 1 ;
if( det( Vector( u[M] - X , y1 - Y ) , Vector( l[M] - X , y2 - Y ) ) < 0 ){
pos = M ;
R = M - 1 ;
}
else
L = M + 1 ;
}
cnt[pos] ++ ;
}
for( int i = 0 ; i <= n ; i++ ){
printf( "%d: %d\n" , i , cnt[i] ) ;
}
puts("");
}
return 0;
}
给一个有很多隔栏的箱子以及一些玩具的坐标,求箱子区域内玩具个数为t(t>0)的区域数。
上一题改改代码顺手A了它。。
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const double eps(1e-6) ;
const int maxn = 5050 ;
struct Point{
int x , y ;
Point( int x = 0 , int y = 0 ) : x(x) , y(y){} ;
} ;
typedef Point Vector ;
int det( Vector a , Vector b ){
return a.x * b.y - a.y * b.x ;
}
int u[maxn] , l[maxn] ;
int cnt[maxn] ;
map<int,int>ms;
int main(){
//freopen("input.txt","r",stdin);
int n , m ;
int x1 , y1 , x2 , y2 ;
while( cin >> n >> m >> x1 >> y1 >> x2 >> y2 && n ){
ms.clear() ;
cls( cnt ) ; cls( u ) ; cls( l ) ;
for( int i = 0 ; i < n ; i++ ){
scanf( "%d%d" , u+i , l+i ) ;
}
sort( u , u+n ) ;
sort( l , l+n ) ;
u[n] = l[n] = x2 ;
for( int i = 0 ; i < m ; i++ ){
int X , Y ;
scanf( "%d%d" , &X , &Y ) ;
int pos ;
int L = 0 , R = n ;
while( L <= R ){
int M = ( L + R ) >> 1 ;
if( det( Vector( u[M] - X , y1 - Y ) , Vector( l[M] - X , y2 - Y ) ) < 0 ){
pos = M ;
R = M - 1 ;
}
else
L = M + 1 ;
}
cnt[pos] ++ ;
}
for( int i = 0 ; i <= n ; i++ ){
ms[cnt[i]] ++ ;
}
map<int,int>::iterator it = ms.begin() ;
puts("Box");
for( ; it != ms.end() ; it++ ){
if( it->first > 0 )
printf("%d: %d\n", it->first , it->second ) ;
}
}
return 0;
}
输入一些线段,问是否存在一条直线使所有线段在直线上的投影都有公共点。
若存在一条直线使所有线段在直线上的投影都有公共点,等价于存在一条直线与所有线段相交。
证明:
存在一条直线使所有线段在直线上的投影都有公共点,作这条直线的垂线,则垂线与所有线段相交。
枚举所有线段的两个端点连成直线,若这条直线经过所有线段,则存在一条直线与所有线段相交。
证明:若存在一条直线与所有线段相交,则可保持该直线与所有线段相交,将其平移至交于某一端点,再旋转该线段,使其交于第二个端点。
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const double eps(1e-10) ;
const int maxn = 100 + 5 ;
struct Point{
double x , y ;
Point( double x = 0 , double y = 0 ) : x(x) , y(y) {}
};
typedef Point Vector ;
Vector operator - ( Point a , Point b ){
return Vector( a.x - b.x , a.y - b.y ) ;
}
double det( Vector a , Vector b ){
return a.x * b.y - a.y * b.x ;
}
int dcmp( double x ){
if( fabs(x) < eps ) return 0 ;
return ( x < 0 )? -1 : 1 ;
}
int segLineCross( Point a1 , Point a2 , Point b1 , Point b2 ){
int d1 = dcmp( det( a2 - a1 , b1 - a1 ) );
int d2 = dcmp( det( a2 - a1 , b2 - a1 ) );
//cout << d1 << ' ' << d2 << endl ;
if( (d1^d2) == -2 )
return 0 ;
if( d1 == 0 || d2 == 0 )
return 1 ;
return -1 ;
}
Point p[maxn << 2] ;
bool check( Point a , Point b , int n ){
if( dcmp( a.x - b.x ) == 0 && dcmp( a.y - b.y ) == 0 )
return false ;
for( int i = 1 ; i < 2 * n ; i += 2 ){
if( segLineCross( a , b , p[i] , p[i+1] ) == -1 )
return false ;
}
return true ;
}
bool work( int n ){
for( int i = 1 ; i < 2 * n ; i++ ){
for( int j = i + 1 ; j <= 2 * n ; j++ ){
if( check( p[i] , p[j] , n ) )
return true ;
}
}
return false ;
}
int main(){
//freopen("input.txt","r",stdin);
int t ; cin >> t ;
while( t-- ){
int n ; cin >> n ;
for( int i = 1 ; i <= 2 * n ; i++ ){
cin >> p[i].x >> p[i].y ;
}
if( work( n ) )
puts( "Yes!" ) ;
else
puts( "No!" ) ;
}
return 0;
}
判断两条直线相交还是平行,重合?
裸题,上模板A过去。
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const double pi = acos( -1.0 ) ;
const double eps = 1e-8 ;
inline double sqr( double x ) { return x * x ; }
inline int cmp( double x ){
if( fabs(x) < eps ) return 0 ;
if( x > 0 ) return 1 ;
return -1 ;
}
struct Point{
double x , y ;
Point(){} ;
Point( double a , double b ):x(a) , y(b){}
void input(){
scanf( "%lf%lf" , &x , &y ) ;
}
double norm(){
return sqrt( sqr( x ) + sqr( y ) ) ;
}
friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }
friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }
friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }
friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }
friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }
friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }
};
typedef Point Vector ;
double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }
double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }
double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }
struct Line{
Point a , b ;
Line(){}
Line( Point x , Point y ): a(x) , b(y){}
};
bool parallel( Line a , Line b ){
return !cmp( det( a.a - a.b , b.a - b.b ) ) ;
}
bool line_make_point( Line a , Line b , Point &res ){
if( parallel( a , b ) ) return false ;
double s1 = det( a.a - b.a , b.b - b.a ) ;
double s2 = det( a.b - b.a , b.b - b.a ) ;
res = ( s1 * a.b - s2 * a.a ) / ( s1 - s2 ) ;
return true ;
}
double dis_to_line( Point P , Point A , Point B ){
Vector v1 = B - A , v2 = P - A ;
return fabs( det( v1 , v2 ) ) / v1.norm() ;
}
int main(){
//freopen("input.txt","r",stdin);
int n ; cin >> n ;
puts("INTERSECTING LINES OUTPUT") ;
while( n-- ){
Point a1 , b1 , a2 , b2 ;
a1.input() ;
b1.input() ;
a2.input() ;
b2.input() ;
Line l1( a1 , b1 ) , l2( a2 , b2 ) ;
Point res ;
if( parallel( l1 , l2 ) && !cmp(dis_to_line( l1.a , l2.a , l2.b )) )
puts( "LINE" ) ;
else if( parallel( l1 , l2 ) && cmp(dis_to_line( l1.a , l2.a , l2.b )) )
puts( "NONE" ) ;
else if( line_make_point( l1 , l2 , res ) ){
printf( "POINT %.2f %.2f\n" , res.x , res.y ) ;
}
}
puts( "END OF OUTPUT" ) ;
return 0;
}
坐标系中有一个10*10的正方形房间,房间中有n面沿y轴方向的墙,每面墙上有两扇门,
求从房间最左边的(0,5)处到达房间最右边的(10,5)处的最短距离
可以算出,总共有4 * n+2个端点,其中包括入口与出口,以及3 * n条障碍线段,那么我们求出来所有点之间的距离,建立邻接矩阵,跑一遍flyod,dijkstra或者spfa都行,总之求出入口到出口的最短路即可。
至于建图方法,判断两个端点所成线段是否与任一障碍线段交,若相交那么距离无穷大,否则计算两点距离。
代码4500B,其中4000B是模板
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const double inf = 10000000 ;
const double pi = acos( -1.0 ) ;
const double eps = 1e-8 ;
inline double sqr( double x ) { return x * x ; }
inline int cmp( double x ){
if( fabs(x) < eps ) return 0 ;
if( x > 0 ) return 1 ;
return -1 ;
}
struct Point{
double x , y ;
Point(){} ;
Point( double a , double b ):x(a) , y(b){}
void input(){
scanf( "%lf%lf" , &x , &y ) ;
}
double norm(){
return sqrt( sqr( x ) + sqr( y ) ) ;
}
friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }
friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }
friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }
friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }
friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }
friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }
};
typedef Point Vector ;
double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }
double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }
double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }
struct Line{
Point a , b ;
Line(){}
Line( Point x , Point y ): a(x) , b(y){}
};
bool segment_inter( Point a1 , Point a2 , Point b1 , Point b2 ){
double c1 = det( a2 - a1 , b1 - a1 ) , c2 = det( a2 - a1 , b2 - a1 ) ,
c3 = det( b2 - b1 , a1 - b1 ) , c4 = det( b2 - b1 , a2 - b1 ) ;
bool tmp = ( ( cmp( c1 ) * cmp( c2 ) < 0 ) && ( cmp( c3 ) * cmp( c4 ) < 0 ) );
return tmp ;
}
const int maxn = 205 ;
vector pt;
vector L;
bool v[maxn] ;
double G[maxn][maxn] ;
double dis[maxn] ;
void build( int n ){
for( int i = 0 ; i < 4 * n + 2 ; i++ ){
for( int j = 0 ; j < 4 * n + 2 ; j++ ){
bool ok = true ;
for( int k = 0 ; k < 3 * n ; k++ ){
if( segment_inter( pt[i] , pt[j] , L[k].a , L[k].b ) ){
ok = false ;
break ;
}
}
if( ok )
G[i+1][j+1] = dist( pt[i] , pt[j] ) ;
else
G[i+1][j+1] = (double)inf ;
}
}
}
double dijkstra( int n ){
for( int i = 1 ; i <= n ; i++ ) dis[i] = G[1][i] ;
dis[1] = 0 ;
cls( v ) ;
for( int i = 1 ; i <= n ; i++ ){
int mark = 1 ;
double mindis = (double)inf ;
for( int j = 1 ; j <= n ; j++ ){
if( !v[j] && dis[j] < mindis ){
mindis = dis[j] ;
mark = j ;
}
}
v[mark] = 1 ;
for( int j = 1 ; j <= n ; j++ )
if( !v[j] && G[mark][j] < inf )
dis[j] = min( dis[j] , dis[mark] + G[mark][j] ) ;
}
return dis[n] ;
}
int main(){
//freopen("input.txt","r",stdin);
int n ;
while( cin >> n && n > -1 ){
pt.clear() ;
L.clear() ;
Point p( 0.0 , 5.0 ) ;
pt.pb(p) ;
for( int i = 1 ; i <= n ; i++ ){
double x , y1 , y2 , y3 , y4 ;
scanf( "%lf%lf%lf%lf%lf" , &x , &y1 , &y2 , &y3 , &y4 ) ;
Point p1( x , y1 ) , p2( x , y2 ) , p3( x , y3 ) , p4( x , y4 ) ;
pt.pb( p1 ) ;
pt.pb( p2 ) ;
pt.pb( p3 ) ;
pt.pb( p4 ) ;
L.pb( Line( Point( x , 0.0 ) , p1 ) ) ;
L.pb( Line( p2 , p3 ) ) ;
L.pb( Line( p4 , Point( x , 10.0 ) ) ) ;
}
pt.pb( Point( 10.0 , 5.0 ) ) ;
build(n) ;
double ans = dijkstra( 4*n + 2 ) ;
printf( "%.2f\n" , ans ) ;
}
return 0;
}
一只仅能左拐的蚂蚁,有n个点要去,要求设计爬行方案,使能去尽可能多的点,且保证爬行轨迹无交叉。
初见惊为神题,百思不得其解,后来知道了极角排序,发现实在是水题啊。。
先看样例1的图:
因为只能左拐,所以起点应尽可能在所有点的最下方,且最左边;
然后对于每一个点,下一个要去的点,要尽可能在以自己为原点,极角较小的方向上,即自己的“右边”,如果极角相同则选择较小距离的点。
然后照着模拟下去就行了,因为没有重点,所以一定可以走完所有点,方案其实就是画一个逆时针螺旋线遍历所有点。
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const double pi = acos( -1.0 ) ;
const double eps = 1e-8 ;
inline double sqr( double x ) { return x * x ; }
inline int cmp( double x ){
if( fabs(x) < eps ) return 0 ;
if( x > 0 ) return 1 ;
return -1 ;
}
struct Point{
double x , y ;
Point(){} ;
Point( double a , double b ):x(a) , y(b){}
void input(){
scanf( "%lf%lf" , &x , &y ) ;
}
double norm(){
return sqrt( sqr( x ) + sqr( y ) ) ;
}
friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }
friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }
friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }
friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }
friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }
friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }
};
typedef Point Vector ;
double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }
double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }
double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }
const int maxn = 55 ;
int pos ;
struct Poi{
Point p ;
int no ;
}last ;
vector p ;
int res[maxn] ;
bool acmp( const Poi &a , const Poi &b ){
int tmp = cmp( det( a.p - last.p , b.p - last.p ) ) ;
if( tmp != 0 ) return tmp > 0 ;
return dist( a.p , last.p ) < dist( b.p ,last.p ) ;
}
bool lowcmp( const Poi &a , const Poi &b ){
if( a.p.y != b.p.y ) return a.p.y < b.p.y ;
return a.p.x < b.p.x ;
}
int main(){
//freopen("input.txt","r",stdin);
int t ; cin >> t ;
while( t -- ){
int n ; cin >> n ;
for( int i = 1 ; i <= n ; i++ ){
Poi t ;
cin >> t.no >> t.p.x >> t.p.y ;
p.pb( t ) ;
}
sort( p.begin() , p.end() , lowcmp ) ;
vector ::iterator it = p.begin() ;
last = *it ;
p.erase( p.begin() ) ;
printf( "%d %d" , n , last.no ) ;
for( int i = 1 ; i < n ; i++ ){
sort( p.begin() , p.end() , acmp ) ;
it = p.begin() ;
last = *it ;
p.erase( p.begin() ) ;
printf( " %d" , last.no ) ;
}
puts("") ;
}
return 0;
}
一个房间被n面墙分成多个密室,告知宝藏坐标,求最少要炸几面墙才能取到宝藏。
其实也算一个大水题,枚举每一面墙的端点与宝藏点所成线段,与所有墙判断是否相交,相交+1,维护最小值,输出的时候+1即可。
ps.注意n = 0 .
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const double pi = acos( -1.0 ) ;
const double eps = 1e-8 ;
inline double sqr( double x ) { return x * x ; }
inline int cmp( double x ){
if( fabs(x) < eps ) return 0 ;
if( x > 0 ) return 1 ;
return -1 ;
}
struct Point{
double x , y ;
Point(){} ;
Point( double a , double b ):x(a) , y(b){}
void input(){
scanf( "%lf%lf" , &x , &y ) ;
}
double norm(){
return sqrt( sqr( x ) + sqr( y ) ) ;
}
friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }
friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }
friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }
friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }
friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }
friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }
};
typedef Point Vector ;
double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }
double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }
double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }
struct Line{
Point a , b ;
Line(){}
Line( Point x , Point y ): a(x) , b(y){}
};
bool segment_inter( Point a1 , Point a2 , Point b1 , Point b2 ){
double c1 = det( a2 - a1 , b1 - a1 ) , c2 = det( a2 - a1 , b2 - a1 ) ,
c3 = det( b2 - b1 , a1 - b1 ) , c4 = det( b2 - b1 , a2 - b1 ) ;
return cmp( c1 ) * cmp( c2 ) < 0 && cmp( c3 ) * cmp( c4 ) < 0 ;
}
const int maxn = 35 ;
Line L[maxn] ;
int main(){
//freopen("input.txt","r",stdin);
int n ;
while( cin >> n ){
for( int i = 1 ; i <= n ; i++ ){
L[i].a.input() ;
L[i].b.input() ;
}
Point p ;
p.input() ;
if( !n ){
printf( "Number of doors = 1\n" ) ;
continue ;
}
int cnt = 0 ;
int ans = 1000000 ;
for( int i = 1 ; i <= n ; i++ ){
cnt = 0 ;
for( int j = 1 ; j <= n ; j++ ){
if( segment_inter( L[i].a , p , L[j].a , L[j].b ) ) cnt++ ;
}
ans = min( ans , cnt ) ;
cnt = 0 ;
for( int j = 1 ; j <= n ; j++ ){
if( segment_inter( L[i].b , p , L[j].a , L[j].b ) ) cnt++ ;
}
ans = min( ans , cnt ) ;
}
ans ++ ;
cout << "Number of doors = " << ans << endl ;
}
return 0;
}
输入两块木板的截面坐标,求能收集多少雨水。
比较恶心的分类讨论。
主要的坑就是:
共线判断,
输出要加eps(可能输出-0.00。
多想想,想清楚。
附赠数据一组:
1
68.22 191.66 257.23 104.97
140.25 33.53 56.71 302.58
正确输出是0.00
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const double pi = acos( -1.0 ) ;
const double eps = 1e-8 ;
inline double sqr( double x ) { return x * x ; }
inline int cmp( double x ){
if( fabs(x) < eps ) return 0 ;
if( x > 0 ) return 1 ;
return -1 ;
}
struct Point{
double x , y ;
Point(){} ;
Point( double a , double b ):x(a) , y(b){}
void input(){
scanf( "%lf%lf" , &x , &y ) ;
}
double norm(){
return sqrt( sqr( x ) + sqr( y ) ) ;
}
friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }
friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }
friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }
friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }
friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }
friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }
};
typedef Point Vector ;
double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }
double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }
double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }
struct Line{
Point a , b ;
Line(){}
Line( Point x , Point y ): a(x) , b(y){}
};
Point line_make_point( Line a , Line b ){
double s1 = det( a.a - b.a , b.b - b.a ) ;
double s2 = det( a.b - b.a , b.b - b.a ) ;
Point res = ( s1 * a.b - s2 * a.a ) / ( s1 - s2 ) ;
return res ;
}
bool segment_inter( Point a1 , Point a2 , Point b1 , Point b2 ){
double c1 = det( a2 - a1 , b1 - a1 ) , c2 = det( a2 - a1 , b2 - a1 ) ,
c3 = det( b2 - b1 , a1 - b1 ) , c4 = det( b2 - b1 , a2 - b1 ) ;
return cmp( c1 ) * cmp( c2 ) <= 0 && cmp( c3 ) * cmp( c4 ) <= 0 ;
}
int main(){
//freopen("my.in","r",stdin);
//freopen("my.out","w+",stdout);
//freopen("input.txt","r",stdin);
int t ; cin >> t ;
while( t-- ){
Line b1 , b2 ;
b1.a.input() ; b1.b.input() ;
if( b1.b.y < b1.a.y ) swap( b1.a , b1.b ) ;
b2.a.input() ; b2.b.input() ;
if( b2.b.y < b2.a.y ) swap( b2.a , b2.b ) ;
if( b1.b.x > b2.b.x ) swap( b1 , b2 ) ;
if( !segment_inter( b1.a , b1.b , b2.a , b2.b ) ){
printf( "0.00\n" ) ;
continue ;
}
double ans ;
Point p = line_make_point( b1 , b2 ) ;
if( b1.b.y < b2.b.y ){
Line h1( b1.b , Point( b1.b.x , b1.b.y + 1000000 ) ) ;
if( segment_inter( h1.a , h1.b , p , b2.b ) ){
printf( "0.00\n" ) ;
continue ;
}
else{
if( cmp( det( b1.b - p , b2.b - p ) ) > 0 ){
Line h2( b2.b , Point( b2.b.x , b2.b.y - 1000000 ) ) ;
Point pp = line_make_point( h2 , b1 ) ;
ans = fabs( det( b2.b - p , pp - p ) / 2.0 ) ;
}
else if( cmp( det( b1.b - p , b2.b - p ) ) < 0 ){
Line h3( b1.b , Point( b1.b.x + 1000000 , b1.b.y ) ) ;
Point pp = line_make_point( h3 , b2 ) ;
ans = fabs( det( b1.b - p , pp - p ) / 2.0 ) ;
}
else{
printf( "0.00\n" ) ;
continue ;
}
}
}
else if( b1.b.y > b2.b.y ){
Line h1( b2.b , Point( b2.b.x , b2.b.y + 1000000 ) ) ;
if( segment_inter( h1.a , h1.b , p , b1.b ) ){
printf( "0.00\n" ) ;
continue ;
}
else{
if( cmp( det( b1.b - p , b2.b - p ) ) > 0 ){
Line h2( b2.b , Point( b2.b.x , b2.b.y - 1000000 ) ) ;
Point pp = line_make_point( h2 , b1 ) ;
ans = fabs( det( b2.b - p , pp - p ) / 2.0 ) ;
}
else if( cmp( det( b1.b - p , b2.b - p ) ) < 0 ){
Line h3( b2.b , Point( b2.b.x - 1000000 , b2.b.y ) ) ;
Point pp = line_make_point( h3 , b1 ) ;
ans = fabs( det( b2.b - p , pp - p ) / 2.0 ) ;
}
else{
printf( "0.00\n" ) ;
continue ;
}
}
}
else if( cmp( b1.b.y - b2.b.y ) == 0 ){
ans = fabs( det( b2.b - p , b1.b - p ) / 2.0 ) ;
}
if( ans > 0 - eps )
printf( "%.2f\n" , ans + eps ) ;
else{
printf( "%.2f\n" , 0.00 + eps ) ;
}
}
return 0;
}
输入一条线段的两个端点,一个矩形的两个顶点,判断线段与矩形是否相交(矩形包括4条边与边内区域)
从题目本身来说是个大水题。。但很考验模板的准确性。
判断为true有这么几种:
- 线段与四条边相交,包括端点相交
- 线段在矩形内
- 线段与四条边重叠共线或首尾相接
其实这题考虑不相交的情况可以简洁许多,至少从代码量上来说是这样的
强烈推荐试试这两组样例
0 18 8 12 1 1 11 11 -> F
9 7 9 2 4 3 9 6 -> T
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const double pi = acos( -1.0 ) ;
const double eps = 1e-8 ;
inline double sqr( double x ) { return x * x ; }
inline int cmp( double x ){
if( fabs(x) < eps ) return 0 ;
if( x > 0 ) return 1 ;
return -1 ;
}
struct Point{
double x , y ;
Point(){} ;
Point( double a , double b ):x(a) , y(b){}
void input(){
scanf( "%lf%lf" , &x , &y ) ;
}
double norm(){
return sqrt( sqr( x ) + sqr( y ) ) ;
}
friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }
friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }
friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }
friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }
friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }
friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }
};
typedef Point Vector ;
double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }
double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }
double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }
struct Line{
Point a , b ;
Line(){}
Line( Point x , Point y ): a(x) , b(y){}
};
bool Onsegment( Point p , Point s , Point t ){
return cmp( det( p - s , t - s ) ) == 0 && cmp( dot( p - s , p - t ) ) <= 0 ;
}
bool parallel( Line a , Line b ){
return !cmp( det( a.a - a.b , b.a - b.b ) ) ;
}
bool segment_inter( Point a1 , Point a2 , Point b1 , Point b2 ){
double c1 = det( a2 - a1 , b1 - a1 ) , c2 = det( a2 - a1 , b2 - a1 ) ,
c3 = det( b2 - b1 , a1 - b1 ) , c4 = det( b2 - b1 , a2 - b1 ) ;
return cmp( c1 ) * cmp( c2 ) < 0 && cmp( c3 ) * cmp( c4 ) < 0 ;
}
int main(){
//freopen("input.txt","r",stdin);
int t ; cin >> t ;
while( t-- ){
Line s ;
s.a.input() ; s.b.input() ;
Point top , bot ;
top.input() ; bot.input() ;
if( bot.x < top.x ){
swap( bot.x , top.x ) ;
}
if( bot.y > top.y ){
swap( bot.y , top.y ) ;
}
Line r1( top , Point( top.x , bot.y ) ) , r2( Point( bot.x , top.y ) , bot ) ;
Line r3( top , Point( bot.x , top.y ) ) , r4( Point( top.x , bot.y ) , bot ) ;
bool ok = false ;
if( segment_inter( r1.a , r1.b , s.a , s.b ) )
ok = true ;
if( segment_inter( r2.a , r2.b , s.a , s.b ) )
ok = true ;
if( segment_inter( r3.a , r3.b , s.a , s.b ) )
ok = true ;
if( segment_inter( r4.a , r4.b , s.a , s.b ) )
ok = true ;
if( Onsegment( s.a , r1.a , r1.b ) || Onsegment( s.b , r1.a , r1.b ) )
ok = true ;
if( Onsegment( s.a , r2.a , r2.b ) || Onsegment( s.b , r2.a , r2.b ) )
ok = true ;
if( Onsegment( s.a , r3.a , r3.b ) || Onsegment( s.b , r3.a , r3.b ) )
ok = true ;
if( Onsegment( s.a , r4.a , r4.b ) || Onsegment( s.b , r4.a , r4.b ) )
ok = true ;
if( parallel( s , r1 ) && s.a.x == r1.a.x ){
if( s.a.y >= min( r1.a.y , r1.b.y ) && s.a.y <= max( r1.a.y , r1.b.y ) )
ok = true ;
if( s.b.y >= min( r1.a.y , r1.b.y ) && s.b.y <= max( r1.a.y , r1.b.y ) )
ok = true ;
if( s.a.y <= min( r1.a.y , r1.b.y ) && s.b.y >= max( r1.a.y , r1.b.y ) )
ok = true ;
if( s.b.y <= min( r1.a.y , r1.b.y ) && s.a.y >= max( r1.a.y , r1.b.y ) )
ok = true ;
}
if( parallel( s , r2 ) && s.a.x == r2.a.x ){
if( s.a.y >= min( r2.a.y , r2.b.y ) && s.a.y <= max( r2.a.y , r2.b.y ) )
ok = true ;
if( s.b.y >= min( r2.a.y , r2.b.y ) && s.b.y <= max( r2.a.y , r2.b.y ) )
ok = true ;
if( s.a.y <= min( r2.a.y , r2.b.y ) && s.b.y >= max( r2.a.y , r2.b.y ) )
ok = true ;
if( s.b.y <= min( r2.a.y , r2.b.y ) && s.a.y >= max( r2.a.y , r2.b.y ) )
ok = true ;
}
if( parallel( s , r3 ) && s.a.y == r3.a.y ){
if( s.a.x >= min( r3.a.x , r3.b.x ) && s.a.x <= max( r3.a.x , r3.b.x ) )
ok = true ;
if( s.b.x >= min( r3.a.x , r3.b.x ) && s.b.x <= max( r3.a.x , r3.b.x ) )
ok = true ;
if( s.a.x <= min( r3.a.x , r3.b.x ) && s.b.x >= max( r3.a.x , r3.b.x ) )
ok = true ;
if( s.b.x <= min( r3.a.x , r3.b.x ) && s.a.x >= max( r3.a.x , r3.b.x ) )
ok = true ;
}
if( parallel( s , r4 ) && s.a.y == r4.a.y ){
if( s.a.x >= min( r4.a.x , r4.b.x ) && s.a.x <= max( r4.a.x , r4.b.x ) )
ok = true ;
if( s.b.x >= min( r4.a.x , r4.b.x ) && s.b.x <= max( r4.a.x , r4.b.x ) )
ok = true ;
if( s.a.x <= min( r4.a.x , r4.b.x ) && s.b.x >= max( r4.a.x , r4.b.x ) )
ok = true ;
if( s.b.x <= min( r4.a.x , r4.b.x ) && s.a.x >= max( r4.a.x , r4.b.x ) )
ok = true ;
}
if( top.x <= min( s.a.x , s.b.x )
&& top.y >= max( s.a.y , s.b.y )
&& bot.y <= min( s.a.y , s.b.y )
&& bot.x >= max( s.a.x , s.b.x ) )
ok = true ;
if( ok )
puts( "T" ) ;
else
puts( "F" ) ;
}
return 0;
}
在房子里看路的视线可能会被障碍物挡住,问从这条路上能看到完整路的最大长度。
盲区范围:房子的左端点与障碍物的右端点所成直线与路的交点p1,房子的右端点与障碍物的左端点所成直线与路的交点p2.盲区即为p2到p1的范围。
求出所有的盲区范围,把所有盲区线段按左端点的x坐标升序排序,然后从左到右扫一遍,维护i之前所有线段的最右端的x坐标last。如果第i个盲区的左端点大于last,那么last到i的左端点的这片区域都是不被覆盖的。扫描每个线段时更新last。
注意障碍物不一定在路与房子之间。
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const double pi = acos( -1.0 ) ;
const double eps = 1e-8 ;
inline double sqr( double x ) { return x * x ; }
inline int cmp( double x ){
if( fabs(x) < eps ) return 0 ;
if( x > 0 ) return 1 ;
return -1 ;
}
struct Point{
double x , y ;
Point(){} ;
Point( double a , double b ):x(a) , y(b){}
void input(){
scanf( "%lf%lf" , &x , &y ) ;
}
double norm(){
return sqrt( sqr( x ) + sqr( y ) ) ;
}
friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }
friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }
friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }
friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }
friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }
friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }
};
typedef Point Vector ;
double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }
double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }
double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }
struct Line{
Point a , b ;
Line(){}
Line( Point x , Point y ): a(x) , b(y){}
};
Point line_make_point( Line a , Line b ){
double s1 = det( a.a - b.a , b.b - b.a ) ;
double s2 = det( a.b - b.a , b.b - b.a ) ;
Point res = ( s1 * a.b - s2 * a.a ) / ( s1 - s2 ) ;
return res ;
}
bool cmp1( Line l1 , Line l2 ){
if( cmp( l1.a.x - l2.a.x ) != 0 )
return l1.a.x < l2.a.x ;
return l1.b.x < l2.b.x ;
}
vector light ;
int main(){
//freopen("input.txt","r",stdin);
double x1 , x2 , y ;
while( cin >> x1 >> x2 >> y ){
if( !x1 && !x2 && !y ) break ;
light.clear() ;
if( x1 > x2 ) swap( x1 , x2 ) ;
Line h( Point( x1 , y ) , Point( x2 , y ) ) ;
cin >> x1 >> x2 >> y ;
Line l( Point( x1 , y ) , Point( x2 , y ) ) ;
int n ;
cin >> n ;
if( n == 0 ){
printf( "%.2f\n" , x2 - x1 ) ;
continue ;
}
for( int i = 1 ; i <= n ; i++ ){
scanf( "%lf%lf%lf" , &x1 , &x2 , &y ) ;
if( y > h.a.y - eps || y < l.a.y + eps ) continue ;
if( x1 > x2 ) swap( x1 , x2 ) ;
Line H( Point( x1 , y ) , Point( x2 , y ) ) ;
Point p1 = line_make_point( Line( h.a , H.b ) , l ) ;
if( p1.x < l.a.x ) p1.x = l.a.x ;
if( p1.x > l.b.x ) p1.x = l.b.x ;
Point p2 = line_make_point( Line( h.b , H.a ) , l ) ;
if( p2.x < l.a.x ) p2.x = l.a.x ;
if( p2.x > l.b.x ) p2.x = l.b.x ;
if( cmp( p1.x - p2.x ) == 0 ) continue ;
else{
light.pb( Line( p2 , p1 ) ) ;
}
}
sort( light.begin() , light.end() , cmp1 ) ;
int s = light.size() ;
if( light.empty() ){
printf( "%.2f\n" , l.b.x - l.a.x ) ;
continue ;
}
double ans = 0 , last = 0 ;
for( int i = 0 ; i < s ; i++ ){
if( light[i].a.x > last ){
ans = max( ans , light[i].a.x - last ) ;
last = light[i].b.x ;
}
else {
last = max( last , light[i].b.x ) ;
}
}
ans = max( ans , l.b.x - last ) ;
if( !cmp( ans ) )
puts( "No View" ) ;
else
printf( "%.2f\n" , ans ) ;
}
return 0;
}