这个是根据网上给的代码整理出来的 :
题目:
一个农夫带着—只狼、一只羊和—棵白菜,身处河的南岸。他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和—件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。请求出农夫将所有的东西运过河的方案。
理解:
// 宏定义
#define MAXNUM 100
// 定义一个函数指针, 名字叫做DataType
typedef int DataType;
// 写结构体的作用是为了把字符串和所对应的函数建立一种联系, 可以用字符串去找到所对应的函数
// 结构体的声明, 确定结构体里包含的内容
struct SeqQueue {
DataType q[MAXNUM];
int f, r; // f是队头, r是队尾
};
typedef struct SeqQueue *pSeqQueue;
// pSeqQueue是一个结构体指针 创建了一个createEmptyQueue_seq的函数
pSeqQueue createEmptyQueue_seq(void) {
pSeqQueue paqu;
// mallco 是指你要开辟的对内存空间大小, 在()里面写的是字节数目
// 通过malloc函数开辟了(struct SeqQueue)这么大小的堆内存空间, 并且返回内存的首地址 为了使用这段内存, 把首地址保存在了一个指针变量paqu中
// sizeof 是判断数据类型或者表达式长度符
paqu = (pSeqQueue)malloc(sizeof(struct SeqQueue));
// 如果paqu这个值是空的, 则直接打印"不在这段空间中"
if (paqu == NULL) {
printf("Out of space !!\n");
} else {
// -> 结构体指针特殊访问方式
// 结构体指针 -> 成员变量 (->这个符号叫做指向操作符)
paqu -> f = 0;
paqu -> r = 0;
}
return (paqu);
}
int isEmptyQueue_seq(pSeqQueue paqu) {
// 判断两个值是不是相等
return (paqu ->f == paqu -> r);
}
// 是循环队列进队
// 两个参数, 一个是pSeqQueue 第二个是DataType
void enQueue_seq(pSeqQueue paqu, DataType x) {
// 算法
if ((paqu ->r + 1) % MAXNUM == paqu ->f) {
printf("Full queue.\n");
} else {
paqu -> q[paqu ->r] = x;
paqu -> r = (paqu ->r + 1) % MAXNUM;
}
}
void deQueue_seq(pSeqQueue paqu) {
if (paqu -> f == paqu -> r) {
printf("Empty Queue.\n");
} else {
paqu ->f = (paqu ->f + 1) % MAXNUM;
}
}
// 创建一个DataType类型的函数指针
DataType frontQueue_seq(pSeqQueue paqu) {
return (paqu -> q[paqu -> f]);
}
// 所谓的确定位置, 就像图片说的, 给一个坑, 找到对应的位置
// & 后面的数字指的就是4个实物的位置, 用二进制标示即为
// 农夫 : 1000
// 野狼 : 0100
// 蔬菜 : 0010
// 山羊 : 0001
int farmer(int location) {
return (0 != (location & 0x08));
}
int wolf(int location) {
return (0 != (location & 0x04));
}
int cabbage(int location) {
return (0 != (location & 0x02));
}
int goat(int location) {
return (0 != (location & 0x01));
}
// 定义一个函数, 根据位置判断三者的安全问题, 如果不安全返回的是0, 如果安全则返回1
int safe(int location) {
if ((goat(location) == cabbage(location)) && (goat(location) != farmer(location))) {
return (0);
}
if ((goat(location) == wolf(location)) && (goat(location) != farmer(location))) {
return (0);
}
return (1);
}
// 创建一个无返回值, 无参数的函数
void framerRiverProblem() {
// 创建三个整型的变量
int movers, location, newLocaton;
// 标示一个整型的一维数组
// 类型说明符 + 数组名[常量表达式\元素的个数]
int route[16]; // 记录已考虑状态的路径
// 创建一个变量
pSeqQueue moveTo;
// 进行赋值
moveTo = createEmptyQueue_seq();
enQueue_seq(moveTo, 0x00);
// 进行遍历 使得route的第一个值是0, 其他的值都被赋值为-1.
for (int i = 0; i < 16; i++) {
route[i] = -1;
}
route[0] = 0;
//!isEmptyQueue_seq(moveTo)"/" && (route[15] == -1) "/": 类似断句的方式, 将过程断开
while (!isEmptyQueue_seq(moveTo) && (route[15] == -1)) {
// 赋值与执行函数
location = frontQueue_seq(moveTo);
deQueue_seq(moveTo);
// movers <<= 1 等价于 a <<= 0, 表示为a左移n位(二进制中) 公式: a * 2 的n次方
for (movers = 1; movers <= 8; movers <<= 1) { // 农夫总是在移动, 随农夫移动的也只能是与农夫同侧的东西
// 进行两次判断, 判断位置的变化, 判断过河的情况
if ((0 != (location & 0x08)) == (0 != (location & movers))) {
newLocaton = location^(0x08 | movers);
if (safe(newLocaton) && (route[newLocaton] == -1)) {
route[newLocaton] = location;
enQueue_seq(moveTo, newLocaton);
}
}
}
}
//判断最后一个元素是不是与我们赋值的-1是相等的
if (route[15] != -1) {
printf("The reverse path is:\n");
// 判断四个事物在和的对面情况, 输出位置的情况
for (location = 15; location >= 0; location = route[location]) {
printf("The location is %d \n", location);
// 判断河的这边最开始的情况
if (location == 0) {
return;
}
}
} else {
// 没有解决的办法
printf("No solution.\n");
}
}