最巧妙的方法是把两只蚂蚁相遇之后看出互相“穿透”。下面是老老实实的计算方法,呵呵。 /**//* * 题目:有一根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 ) { returnfalse; } /**//* * 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 ); returntrue; } elseif( b->pos - a->pos ==0 ) { turn_round( a ); turn_round( b ); returnfalse; } } returnfalse; } 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] ={ 3, 7, 11, 17, 23 }; 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 return0; }