现在的位置: 首页 > 综合 > 正文

ZOJ 1721 The Doors

2018年03月18日 ⁄ 综合 ⁄ 共 3989字 ⁄ 字号 评论关闭

一道很好的DP题。预处理每个点对之间是否能直接到达,然后状态很容易划分。

#include <stdio.h>
#include 
<string.h>
#include 
<math.h>

#define _0 1e-10

int N, b[20][4][20][4], ll;
double f[20][4];

typedef 
struct
{
    
double x, y[4];
}
 Wall;
Wall w[
20];

typedef 
struct
{
    
double x, y;
}
 Point;

typedef 
struct
{
    
double x1, y1, x2, y2;
}
 Line;
Line l[
100];

void pf ()
{
    
int i, j, ii, jj;
    
for ( i = 1; i <= N; i ++ )
    
{
        
for ( j = 0; j < 4; j ++ )
        
{
            printf ( 
"%d ", b[i][j][3][0] );
        }

        printf ( 
" " );
    }

}


double crossDet ( double x1, double y1, double x2, double y2 )
{
    
return x1 * y2 - x2 * y1;
}


double cross ( Point &a, Point &b, Point &c )
{
    
return crossDet ( b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y );
}


double dCmp ( double x )
{
    
if ( x <_0 && x> - _0 )
        
return 0;
    
return x > _0 ? 1 : -1;
}


double dist ( double x1, double y1, double x2, double y2 )
{
    
return sqrt ( ( y1 - y2 ) * ( y1 - y2 ) + ( x1 - x2 ) * ( x1 - x2 ) );
}



int segCross ( Point &a, Point &b, Point &c, Point &d )
{
    
return ( dCmp ( cross ( a, b, d ) ) * dCmp ( cross ( a, b, c ) ) == -1 ) &&
           ( dCmp ( cross ( c, d, a ) ) 
* dCmp ( cross ( c, d, b ) ) == -1 );
}


int reach ( double x1, double y1, double x2, double y2 )
{
    
//x1 < x2
    int i;
    
for ( i = 0; i < ll; i ++ )
    
{
        
//if ( x1 >= l[i].x1 || x2 <= l[i].x1 )
            
//continue;
        Point p1, p2, p3, p4;
        p1.x 
= x1, p1.y = y1, p2.x = x2, p2.y = y2;
        p3.x 
= l[i].x1, p3.y = l[i].y1, p4.x = l[i].x2, p4.y = l[i].y2;
        
if ( segCross ( p1, p2, p3, p4 ) )
            
return 0;
    }

    
return 1;
}


int init ()
{
    scanf ( 
"%d"&N );
    memset ( b, 
0sizeof ( b ) );
    
if ( N == -1 )
        
return 0;
    
int i, j, ii, jj;
    
for ( i = 1; i <= N; i ++ )
        scanf ( 
"%lf%lf%lf%lf%lf"&w[i].x, &w[i].y[0], &w[i].y[1], &w[i].y[2], &w[i].y[3] );
    
for ( i = 1, ll = 0; i <= N; i ++ )
    
{
        l[ll].x1 
= l[ll].x2 = w[i].x, l[ll].y1 = 0, l[ll ++].y2 = w[i].y[0];
        l[ll].x1 
= l[ll].x2 = w[i].x, l[ll].y1 = w[i].y[1], l[ll ++].y2 = w[i].y[2];
        l[ll].x1 
= l[ll].x2 = w[i].x, l[ll].y1 = w[i].y[3], l[ll ++].y2 = 10;
    }

    
for ( i = 1; i <= N; i ++ )
        
for ( j = 0; j < 4; j ++ )
        
{
            
if ( reach ( 05, w[i].x, w[i].y[j] ) )
                b[i][j][
0][0= b[0][0][i][j] = 1;
            
if ( reach ( 105, w[i].x, w[i].y[j] ) )
                b[i][j][N 
+ 1][0= b[N + 1][0][i][j] = 1;
            
for ( ii = i + 1; ii <= N; ii ++ )
                
for ( jj = 0; jj < 4; jj ++ )
                    
if ( reach ( w[i].x, w[i].y[j], w[ii].x, w[ii].y[jj] ) )
                        b[i][j][ii][jj] 
= b[ii][jj][i][j] = 1;
        }

    
return 1;
}


void dp ()
{
    
if ( reach ( 05105 ) )
    
{
        printf ( 
"%.2f "10.00 );
        
return;
    }

    
int i, j, ii, jj;
    
double t, tt;
    
for ( i = 1; i <= N; i ++ )
    
{
        
for ( j = 0; j < 4; j ++ )
        
{
            t 
= 100;
            
if ( b[i][j][0][0] )
            
{
                f[i][j] 
= dist ( 05, w[i].x, w[i].y[j] );
                
continue;
            }

            
for ( ii = 1; ii < i; ii ++ )
            
{
                
for ( jj = 0; jj < 4; jj ++ )
                
{
                    
if ( b[i][j][ii][jj] )
                    
{
                        tt 
= f[ii][jj] + dist ( w[i].x, w[i].y[j], w[ii].x, w[ii].y[jj] );
                        
if ( t > tt )
                            t 
= tt;
                    }

                }

            }

            f[i][j] 
= t;
        }

    }

    
double ans = 100;
    
for ( i = 1; i <= N; i ++ )
    
{
        
for ( j = 0; j < 4; j ++ )
        
{
            
if ( b[i][j][N + 1][0] )
            
{
                tt 
= f[i][j] + dist ( w[i].x, w[i].y[j], 105 );
                
if ( ans > tt )
                    ans 
= tt;
            }

        }

    }

    printf ( 
"%.2f ", ans );
}


int main ()
{
    
//freopen ( "in.txt", "r", stdin );
    while ( init () )
    
{
        dp ();
        
//pf ();
    }

    
return 0;
}

 

【上篇】
【下篇】

抱歉!评论已关闭.