1问题描述

一个农夫在河边要过河,但是他带着一匹狼、一只羊和一颗白菜。他需要用船将这三样东西运至对岸,然而,这艘船的空间有限,只容得下他自己和另一样东西(或狼或羊或白菜)。若他不在场看管的话,狼就会吃羊,羊就会去吃白菜。此人如何才能过河。

2、问题分析

根据题意我们可以得出一下结论:

(1)三样东西必须都过河,但是一次只能载一个;

(2)如果农夫不在场,那么狼会吃羊,羊会吃白菜。

3、算法概述

对于此题,抽象成编程问题来解决。将人、狼、羊、菜在此岸都设为1,当成功渡河后则都为0。用类bankState来表示河岸的状态,用类boatState来表示船上的状态。用time来表示运载的次数。

如此一来,问题转化成判断所有的1是不是都转化为0了,以及其中两个在一起时是否合法的问题了。

4、详细设计

按照人、狼、羊、菜的顺序描述,为了描述方便,假设在河岸A,要过河到达到河岸B。其中,人、狼、羊、菜只能为01,其他值都是非法的。

新建类boatState用来描述船上的状态,可知船上的状态只有4种可能,即人自己、人和狼、人和羊、人和菜,用实例化对象boat[4]来表示这四种状态。

新建类bankState用来描述河岸的状态,实例化对象stateA[record]用来记录河岸A的状态,stateB[record]用来记录河岸B的状态,其中record为可能需要的最大次数。

初始化stateA[0]值为{1,1,1,1},实例化boat[4],其可取值为{1,0,0,0}{1,1,0,0}{1,0,1,0}{1,0,0,1}用于判断船上状态是否合法。

开始渡河。依次判断是否已经全为0,即是否已经成功渡河。若成功,则打印过河过程中河岸A的所有状态,否则继续判断。判断状态是否合法,状态是否出现过已经,若都通过,则进行渡河操作,开始进行递归。

5、运行结果

农夫、狼、羊、菜过河简单算法分析_算法

6、经验总结

通过这次程序设计,首先,对于类的封装性有了新的认识,因为在编写过程中屡次出现非法访问成员变量,现在终于懂了那么一点了,不再停留于模模糊糊的认识了。其次,对于友元函数也有了一定的认识,因为用到了。对于递归的判断有了新的认识。程序很简单,同时也有很多不足之处,所以发表出来,希望大家能够共同学习,共同进步!

7、源码

#include <iostream>

using namespace std;

class boatState;
class bankState;

class boatState				//the state of boat
{
	public:
		boatState(){}
		boatState(int p, int w, int s, int c);
	private:
		int m_person;
		int m_wolf;
		int m_sheep;
		int m_cabbage;

		friend class bankState;	//let the bankState access to the boatState
};
boatState::boatState(int p, int w, int s, int c)
{
	m_person = p;
	m_wolf = w;
	m_sheep = s;
	m_cabbage = c;
}

class bankState			//the state of bank
{
	public:
		bankState(){}
		bankState(int p, int w, int s, int c);
		void display();				//output the result to the screen
		int compareToEnd();			//confirm whether is the end
		int notAllow();				
		               //confirm whether the state is allowed
		int compareToAppear(bankState temp);	
		               //confirm the state has never appeared
		void newState(bankState &tempState, boatState tempBoat);
		                                        //the new state of bankA
		void otherState(bankState &tempB);	//the state of bankB
	private:
		int m_person;
		int m_wolf;
		int m_sheep;
		int m_cabbage;
};
bankState::bankState(int p, int w, int s, int c)
{
	m_person = p;
	m_wolf = w;
	m_sheep = s;
	m_cabbage = c;
}
void bankState::display()
{
	cout << m_person << m_wolf << m_sheep << m_cabbage << endl;
}
int bankState::compareToEnd()
{
	if(m_person == 0 && m_wolf == 0 && m_sheep == 0 && m_cabbage == 0)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
int bankState::notAllow()
{
	if (m_person == 0 && ((m_wolf == 1 && m_sheep == 1 && m_cabbage == 1 )
	 || (m_wolf == 1 && m_sheep == 1) || (m_sheep == 1 && m_cabbage == 1)))
	{
		return 1;
	}
	else
	{
		if ((m_person != 0 && m_person != 1) || (m_wolf != 0 && m_wolf != 1) 
		|| (m_sheep != 0 && m_sheep != 1) || (m_cabbage != 0 && m_cabbage != 1))
		{
			return 1;
		}
		else
		{
			return 0;
		}
	}
}
int bankState::compareToAppear(bankState temp)
{
	if (m_person == temp.m_person && m_wolf == temp.m_wolf 
	&& m_sheep == temp.m_sheep && m_cabbage == temp.m_cabbage)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
void bankState::newState(bankState &tempState, boatState tempBoat)
{
	if (m_person == 1)
	{
		tempState.m_person = m_person - tempBoat.m_person;
		tempState.m_wolf = m_wolf - tempBoat.m_wolf;
		tempState.m_sheep = m_sheep - tempBoat.m_sheep;
		tempState.m_cabbage = m_cabbage - tempBoat.m_cabbage;
	}
	if (m_person == 0)
	{
		tempState.m_person = m_person + tempBoat.m_person;
		tempState.m_wolf = m_wolf + tempBoat.m_wolf;
		tempState.m_sheep = m_sheep + tempBoat.m_sheep;
		tempState.m_cabbage = m_cabbage + tempBoat.m_cabbage;
	}
}
void bankState::otherState(bankState &tempB)
{
	tempB.m_person = 1 - m_person;
	tempB.m_wolf = 1 - m_wolf;
	tempB.m_sheep = 1 - m_sheep;
	tempB.m_cabbage = 1 - m_cabbage;
}

const int record = 20;
bankState stateA[record];
bankState stateB[record];
boatState boat[4];

void crossRiver(int time)
{
	if (stateA[time].compareToEnd())
	{
		cout << "Success!" << endl;
		for (int num = 0; num <= time; num++)
		{
			stateA[num].display();
		}
		return;
	}
	if (stateA[time].notAllow() || stateB[time].notAllow())
	{
		return;
	}
	for (int i = 0; i < time; i++)
	{
		if (stateA[time].compareToAppear(stateA[i]))
		{
			return;
		}
	}
	for (int j = 0; j < 4; j++)
	{
		stateA[time].newState(stateA[time + 1], boat[j]);
		stateA[time + 1].otherState(stateB[time + 1]);
		crossRiver(time + 1);
	}

}

void main()
{
	//init the state
	stateA[0] = bankState(1, 1, 1, 1);
	boat[0] = boatState(1, 0, 0, 0);
	boat[1] = boatState(1, 1, 0, 0);
	boat[2] = boatState(1, 0, 1, 0);
	boat[3] = boatState(1, 0, 0, 1);

	crossRiver(0);

	system("pause");
}