faraway  
最巧妙的方法是把两只蚂蚁相遇之后看出互相“穿透”。下面是老老实实的计算方法,呵呵。

/*
 *    题目:有一根27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。
 *    木杆很细,不能同时通过一只蚂蚁。开始时,蚂蚁的头朝左还是朝右是任意的
 *    它们只会朝前走或调头,但不会后退。
 *    当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。假设蚂蚁们每秒钟可以走一厘米的距离。
 *    编写程序,求所有蚂蚁都离开木杆的最小时间和最大时间。
 
*/


/*
 *              1         2          
 *    0123456789012345678901234567
 *       +   +   +     +     +
 *    ---+---+---+-----+-----+----
 *
 *    从左至右构成链表,从左端开始检查相邻蚂蚁是否相遇,是否需要移动(相距1cm时无需移动,仅改变方向)
 *    到达两端后从链表中删除
 *
 
*/


#include 
<stdio.h>
#include 
<stdlib.h>

#define ALL 1

#if ALL
#define DETAIL 0
#else
#define DETAIL 1
#endif

#define ANT_NUM 5
#define LENGTH 27

#define LEFT -1
#define RIGHT 1

typedef 
struct ant_struct {
    
struct ant_struct *    left;    // nearly ant on the left
    struct ant_struct *    right;    // nearly ant on the right
    int                    index;
    
int                    pos;    // current position, from 0 to n
    int                    dir;    // which direction, left or right
    int                    time;    // elapsed time
}
 ant;

void print_state( ant* s )
{
    ant
* p;

    p 
= s->right;
    
while ( p ) {
        printf(
"(%d) postion: %2d direction: %s\n", p->index, p->pos,
                (p
->dir==LEFT)?"left":((p->dir==RIGHT)?"right":"Bad direction"));
        p 
= p->right;
    }

}


void set_direction( ant* head, int dir )
{
    ant
* p = head->right;

    
while ( p ) {
        
if ( dir % 2 )
            p
->dir = RIGHT;
        
else
            p
->dir = LEFT;
        dir 
>>= 1;
        p 
= p->right;
    }

}


ant
* init_state( int* pos, int dir, int ant_num )
{
    ant
* head;
    ant
* p;
    ant
* q;
    
    
if ( (head = (ant *)malloc( sizeof(ant))) == NULL )
        exit(
1);

    head
->pos = 0;
    head
->dir = 0;
    head
->left = NULL;
    head
->right = NULL;

    q 
= head;

    
for ( int i = 0; i < ant_num; i++ ) {
        
if ( (p = (ant *)malloc( sizeof(ant))) == NULL )
            exit(
1);

        p
->index    = i + 1;
        p
->pos        = pos[i];
        p
->time        = 0;

        p
->left        = q;
        q
->right    = p;
        p
->right    = NULL;

        q 
= q->right;
    }

    set_direction( head, dir );

    
return head;
}


void turn_round( ant* p )
{
    p
->dir = -(p->dir);
}


bool ismoved( ant* a, ant* b)
{
    
if ( a == NULL )
        exit(
1);
    
if ( b == NULL ) {
        
return false;
    }


    
/*
     *    if there are 1 CM between a and b, they will meet and turn round 
     *    and return to the initial position in the 1 second.
     *    if there are 0, they have meet and turn round now.
     *    otherwise they will go along their direction
     
*/

    
if ( a->dir == RIGHT && b->dir == LEFT ) {
        
/*    meet and change its direction    */
        
if ( b->pos - a->pos == 1 ) {
            turn_round( a );
            turn_round( b );

            
return true;
        }

        
else if( b->pos - a->pos == 0 ) {
            turn_round( a );
            turn_round( b );

            
return false;
        }

    }


    
return false;
}


void moveall( ant* head )
{
    ant
* p = head->right;

    
while ( p ) {
        
if ( ismoved( p, p->right ) == false ) {
            
/*    move towards its direction */
            p
->pos += p->dir;
            p
->time++;

            
/*    check whether it has gone out    */
            
if ( p->pos == 0 || p->pos == LENGTH ) {
                
/*    delete the ant    */
#if DETAIL
                printf(
"(%d) ant goes out at %d\n", p->index, p->time);
#endif
                
/*    
                 *    if p is not at the end of list, the right node
                 *    point to the left node.
                 *    
*/

                
if ( p->right ) {
                    
/*    remove the ant at the begin of list    */
                    p
->right->left = p->left;
                    p
->left->right = p->right;
                    free( p );
                    p 
= head;
                }

                
else {
                    
/* reach the end of list, remove the ant */
                    p
->left->right = p->right;
                    free( p );
                    
break;
                }

            }

        }


        
/*    check next ant    */
        p 
= p->right;
    }

}


/*    one possibility    */
int process( int* pos, int dir, int ant_num )
{
    ant
* s;
    
int time = 1;

    s 
= init_state( pos, dir, ant_num );

    
/* keep moving util no ants    */
    
while ( s->right ) {
        
/* move all ants in a second    */
        moveall( s );
#if DETAIL
        printf(
"\ntime:%d\n", time);
        print_state( s );
#endif
        time
++;
    }


    printf(
"total time:%d\n", time);

    
return time;
}


int main( void )
{
    
int pos[ANT_NUM] = 37111723 };
    
int ant_num = ANT_NUM;
    
int max = 0;
    
int min = 10000;
    
int now;
    
int possibility = (1<<ANT_NUM) - 1;

#if ALL
    
while ( possibility >= 0 ) {

        now 
= process( pos, possibility, ant_num );
        
if ( now < min ) min = now;
        
if ( now > max ) max = now;
        printf(
"----possibility:%2d  max:%2d  min:%2d----\n\n", possibility, max, min);

        possibility
--;
    }


    printf(
"max time:%d, min time:%d\n", max, min);
#else
    process( pos, 
4, ant_num );
#endif

    
return 0;
}


posted on 2008-07-15 09:43  faraway  阅读(394)  评论(0编辑  收藏  举报