狼羊菜过河(C实现)

        题目描述:农夫需要把狼、羊、菜和自己运到河对岸去,只有农夫能够划船,而且船比较小,除农夫之外每次只能运一种东西,还有一个棘手问题,就是如果没有农夫看着,羊会偷吃菜,狼会吃羊。请考虑一种方法,让农夫能够安全地安排这些东西和他自己过河。

        在大学期间我记得碰到这种问题,第一感觉就是用递归,当时狭义的认为递归算法就是:必须有自身调用自身的函数方法!否则就是没有递归思想。直到最近一次阅读nginx源码中的红黑树实现,发现源码中对红黑树节点插入、旋转的代码也是运用递归思想,但是就是在一个while循环中实现的,于时茅塞顿开!原来递归思想的实现不仅仅局限于一种实现方式,换句话说:函数实现中自身调用自身一定是用了递归思想,但递归思想不一定只有函数自身调用自身一种实现方式

        记得大学时候写的递归特别复杂,限于当时对算法的理解误区,现在也想不清当时的实现细节了。下面是我重新实现的一次,具体代码如下:

/************************************************
***		Author : lijd	
***		Date   : 2022-11-18
***		Func   : 狼羊菜过河算法实现
************************************************/
#include <stdio.h>

// 用二维数组表示变量
// 一维下标 t[i], i = 0 : 为河岸一边,i = 1 : 河对岸
// 二维下标 t[i][j], j = 0:菜, j = 1:羊, j = 2:狼, j = 3:农夫
char t[2][4] = {{1, 1, 1, 1}, {0, 0, 0, 0}};

char name[3][10] = {"菜", "羊", "狼"};

void guohe()
{
	int i = 0;
	// 当有一个没有过河
	while(t[1][0] != 1 || t[1][1] != 1 || t[1][2] != 1 || t[1][3] != 1)
	{
		// 农夫没过河
		if(t[0][3] == 1)
		{
			// 农夫过河
			t[0][3] = 0;	t[1][3] = 1;
			
			// 带东西过河
			for(i = 0; i < 3; i++)
			{
				if(t[0][i] == 1)	
				{	
					// 假设菜跟狼都已过河
					if((t[1][0] == 1 && t[1][2] == 1) && i == 1)
					{
						// 则带羊过河
						t[0][1] = 0;	t[1][1] = 1;
						printf("农夫带%s过河\n", name[1]);
						break;
					}
					
					// 假设菜跟狼仅只有一个过河, 不能带羊过河,防止死循环
					if((t[1][0] == 1 || t[1][2] == 1) && i == 1)
					{
						continue;
					}
					
					// 假设将i带过河 不满足被吃条件 continue跳过
					t[0][i] = 0;
					if((t[0][0] == 1 && t[0][1] == 1) ||(t[0][1] == 1 && t[0][2] == 1))
					{
						t[0][i] = 1;
						continue;
					}
					
					// 则带i过河
					t[0][i] = 0;	t[1][i] = 1;
					printf("农夫带%s过河\n", name[i]);
					break;
				}
			}
		}
		// 农夫已过河
		else
		{	
			// 农夫回过河
			t[0][3] = 1;	t[1][3] = 0;
			
			// 判断是否要带回东西过河
			if((t[1][0] == 1 && t[1][1] == 1) || (t[1][1] == 1 && t[1][2] == 1))
			{
				// 让羊回过河
				t[0][1] = 1;	t[1][1] = 0;
				printf("农夫带羊回过河\n");
			}else{
				printf("农夫自己回过河\n");
			}
		}
	}
}

int main()
{
	guohe();
	
	return 0;
}

        代码编译运行结果如下:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值