有一根27厘米的细木杆,在杆上某些位置上各有一只蚂蚁。木杆很细,不能同时通过一只以上蚂蚁。开始时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,但不会后退。当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。假设蚂蚁们每秒钟可以走一厘米的距离。编写程序,输出各时刻杆上蚂蚁的位置和方向,每个时刻离杆的蚂蚁的编号,所有蚂蚁的离杆时间。最后输出各蚂蚁离杆时间。
代码如下(C语言):
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
struct ant //保存蚂蚁信息的结构体类型
{
struct ant* next;
struct ant* before;
short direction; //蚂蚁位置
int position; //蚂蚁方向
int sign; //蚂蚁编号
};
struct ant2
{
int time;
int sign;
struct ant2* next;
};
struct ant3
{
int sign;
struct ant3* next;
};
typedef struct ant node;
typedef struct ant2 node2;
typedef struct ant3 node3;
void processAntOutBound(node *q, node3 *&q3, int t, node2 *head2)
{
node3 *psnew3 = (node3*)malloc(sizeof(node3));
psnew3->sign = q->sign; //保存越界的蚂蚁节点
psnew3->next = NULL;
q3->next = psnew3;
q3 = psnew3;
node2 *psnew2 = (node2*)malloc(sizeof(node2));
psnew2->sign = q->sign; //建立另一个越界的蚂蚁节点,保存该蚂蚁离杆的时间
psnew2->time = t;
if (head2->next == NULL)
{
psnew2->next = NULL;
head2->next = psnew2;
}
else
{
node2 *t2 = head2;
node2 *q2 = head2->next;
while (1)
{
if ((psnew2->sign) < (q2->sign) || q2->next == NULL) //对越界的蚂蚁节点执行插入排序
{
if ((psnew2->sign) < (q2->sign))
{
psnew2->next = q2;
t2->next = psnew2;
}
else
{
q2->next = psnew2;
psnew2->next = NULL;
}
break;
}
else
{
t2 = t2->next;
q2 = q2->next;
}
}
}
}
void main()
{
int t, i, flag;
int* p1;
int* p2;
struct ant* psnew, * q, * head, * front, * after, * tail;
struct ant2 * q2, * head2;
struct ant3* head3, * psnew3, * q3;
printf("please input the number of ants in stick\n"); /*输入位于杆上的蚂蚁个数,不能为0,数量不超过27*/
scanf_s("%d", &t);
p1 = (int*)malloc(t * sizeof(int));
p2 = (int*)malloc(t * sizeof(int));
for (i = 0; i < t; i++)
{
printf("please input the direction of %dnd ant\n", i + 1); /*输入第i+1个蚂蚁的初始方向,1表示向右,0表示向左*/
scanf_s("%d", p1 + i);
printf("pleaase input the position of %dnd ant\n", i + 1); /*输入第i+1个蚂蚁的初始位置,杆长27cm,位置为蚂蚁所在处距杆左端的长度,只能为正整数,即位置只能为1cm,2cm,3cm---,26cm,27cm,位置需按照蚂蚁编号从小到大输入*/
scanf_s("%d", p2 + i);
}
head = (node*)malloc(sizeof(node));
q = head;
head->next = NULL;
head->before = NULL;
for (i = 0; i < t; i++)
{
psnew = (node*)malloc(sizeof(node));
psnew->next = NULL;
psnew->direction = p1[i]; //初始化蚂蚁队列和各蚂蚁刚开始的位置方向
psnew->position = p2[i];
psnew->sign = i + 1;
q->next = psnew;
psnew->before = q;
q = psnew;
}
tail = q;
head3 = (node3*)malloc(sizeof(node3));
head3->next = NULL;
q3 = head3;
head2 = (node2*)malloc(sizeof(node2));
head2->next = NULL;
q2 = head2;
t = 0;
while (head != tail) /*判断线性链表是否为空链表,从而判断是否全部的蚂蚁都爬下了杆子,若是退出循环输出t,否则继续循环*/
{
t++; /*时间进一过度到下一个时间点*/
q = head->next;
while (q != NULL) /*检测当前节点对应的蚂蚁的方向,根据方向调整蚂蚁的位置*/
{
if (q->direction)
q->position = q->position + 1; /*这种位置调整方式存在漏洞.若某时刻前一蚂蚁与后一蚂蚁位置相隔1,前一蚂蚁向右运动,后一蚂蚁向左运动,则按这种方式时间进一后前一蚂蚁将爬到后一蚂蚁前面一格,换言之两只蚂蚁位置交换了*/
else /*换言之两只蚂蚁互相穿过了对方,这是不可能的,实际上时间进一后两只蚂蚁仍在原来的位置,两只蚂蚁在他们原来两个位置的中点相碰又回到了原来的位置,并且此时他们的方向应该和原来方向相反*/
q->position = q->position - 1; /*因此需要对两只蚂蚁的位置方向进行修正,此外若时间进一所有蚂蚁按照各自的方向移动一格后,两只蚂蚁位置相同,即他们相对碰撞,则碰撞后蚂蚁运动方向和原来相反,因此也需要修正方向.*/
q = q->next;
}
psnew = head->next; /*psnew指向第一个节点*/
if (psnew->next != NULL) /*判断第一个节点是否为尾节点,若不是说明有两只以上蚂蚁,则进行碰撞检测,修正蚂蚁运动方向,以及对发生相互穿越错误的一对蚂蚁的位置方向进行修正*/
{
q = psnew;
psnew = head;
flag = 1;
do
{
psnew = psnew->next;
q = q->next;
if ((psnew->position) > (q->position) || ((psnew->position) == (q->position)) && flag) /*检测发生相互穿越错误的一对蚂蚁并对其位置和方向进行修正*/
{
i = psnew->direction;
psnew->direction = q->direction;
q->direction = i;
if ((psnew->position) > (q->position))
{
i = psnew->position;
psnew->position = q->position;
q->position = i;
front = psnew->before;
if (front->before != NULL)
{
if (front->position == psnew->position) /*进行碰撞检测,对碰撞后蚂蚁的方向进行修正*/
{
i = front->direction;
front->direction = psnew->direction;
psnew->direction = i;
if (q->next != NULL)
{
after = q->next;
if (after->position == q->position)
{
i = after->direction;
after->direction = q->direction;
q->direction = i;
flag = 0;
}
}
}
}
}
}
else
{
flag = 1;
}
} while (q->next != NULL);
}
q = head->next; /*蚂蚁的方向位置都修正完毕后对首尾节点对应的蚂蚁的位置进行检测,判断蚂蚁是否爬下杆子*/
if ((q->position < 1) || (q->position >= 27))
{
processAntOutBound(q, q3, t, head2);
if (q == tail)
{
tail = head;
}
head->next = q->next;
if (q->next != nullptr) //如果首位处蚂蚁离杆则删除对应节点
{
q->next->before = head;
}
free(q);
}
if (tail != head && (tail->position < 1) || (tail->position >= 27))
{
processAntOutBound(tail, q3, t, head2);
q = tail->before;
free(tail);
q->next = nullptr;
tail = q;
}
q = head;
while (q != tail)
{
q = q->next;
printf("at the time%d,the%dnd ant is at the position%d,in the direction%d\n", t, q->sign, q->position, q->direction); /*输出当前时刻杆上所有蚂蚁的编号,位置,方向*/
}
q3 = head3->next;
while (q3 != NULL)
{
printf("The %dnd ant is off the stick at time%d\n", q3->sign, t); //输出当前时间t离杆的蚂蚁编号
q3 = q3->next;
}
q3 = head3;
while (q3->next != NULL)
{
psnew3 = q3->next;
q3->next = psnew3->next;
free(psnew3);
}
}
printf("the time of all ants need to be off the stick is %d\n", t); /*输出全部蚂蚁爬下杆子所对应时刻(蚂蚁均位于初始位置时视为t=0时刻),也就是蚂蚁全部爬出杆子所需时间*/
printf("\n");
q2 = head2->next;
while (q2 != NULL)
{
printf("The %dnd ant is off the stick at time%d\n", q2->sign, q2->time); //输出各蚂蚁离杆时间
q2 = q2->next;
}
}
/*用线性链表实现解决蚂蚁问题,若干蚂蚁位于一长杆上,杆长27cm,蚂蚁初始方向可以任意,运动速度1cm/s,蚂蚁从初始位置出发,两蚂蚁若相碰不能穿过对方,只能相碰后各自掉头,求蚂蚁全部爬出杆子所需时间*/
当初始时刻木杆有三只蚂蚁,从左至右数第一只蚂蚁位置方向为3,1,第二只为4,0,第三只为5,0时输出结果如下: