问题描述
一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸,他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜;否则狼会吃羊,羊会吃白菜。所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。要求给出农夫将所有的东西运过河的方案。
功能设计
- 用户输入起始状态,输入终止状态
- 判断输入是否合法
- 判断输入的状态是否安全
- 获取农夫、狼、白菜、羊的位置
- 输出运输方案
- 判断是否继续
实现思想
- 用4位二进制数顺序分别表示农夫、狼、白菜、羊的位置。0表示在南岸,1表示在北岸
- 使用按位与操作来确定每个角色所在位置的代码是0还是1。函数返回值为真,表示在北岸,否则在南岸
- 通过位置分布来判断当前状态是否安全。若状态安全返回1,否则返回0
- 将初始状态存入队列,并将存储状态路径的数组除初始状态位置置为当前状态所表示的十进制数外全部置为-1,表示未记录过路径
- 利用广度优先遍历从初始状态开始依次考虑农夫可能的选择,并判断过河的可能性。如果渡河后状态安全,则将其状态入队并将当前状态的索引记录到路径数组中,下标索引为后续状态值。若渡河后状态不安全,则继续考虑后面一个选择
- 若农夫、狼、白菜、羊这四种选择都考虑完成,则将队列中的元素出队,继续考虑新状态下农夫可能的选择和过河的可能性,直到队列为空或者路径数组下标索引值为终止状态的值被访问过了
- 从终止状态开始,根据路径数组的下标输出运输方案
代码
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 16
typedef int data;
typedef struct queue{
data a[MAXSIZE];
int front,rear; //front队头,rear队尾
}SeqQueue, * Seq;
// 创建队列
Seq create(){
Seq s;
s = (Seq)malloc(sizeof(SeqQueue));
s->front = 0;
s->rear = 0;
return(s);
}
//判断是否为空
int isEmpty(Seq s){
return( s->front == s->rear );
}
//判断是否为满
int isFull(Seq s){
return( (s->rear+1)%MAXSIZE == s->front);
}
// 入队
int insert(Seq s, data x){
if(isFull(s)){
printf("FULL!\n");
return 1;
}
else{
s->a[s->rear] = x;
s->rear = (s->rear + 1) % MAXSIZE;
return 0;
}
}
// 出队
int dele(Seq s, data *d){
if(isEmpty(s)){
printf("Empty!\n");
return 0;
}
else{
*d = s->a[s->front];
s->front = (s->front +