最巧妙的方法是把两只蚂蚁相遇之后看出互相“穿透”。下面是老老实实的计算方法,呵呵。
/*
* 题目:有一根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] = { 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
return 0;
}
/*
* 题目:有一根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] = { 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
return 0;
}