1、问题描述
一个农夫在河边要过河,但是他带着一匹狼、一只羊和一颗白菜。他需要用船将这三样东西运至对岸,然而,这艘船的空间有限,只容得下他自己和另一样东西(或狼或羊或白菜)。若他不在场看管的话,狼就会吃羊,羊就会去吃白菜。此人如何才能过河。
2、问题分析
根据题意我们可以得出一下结论:
(1)三样东西必须都过河,但是一次只能载一个;
(2)如果农夫不在场,那么狼会吃羊,羊会吃白菜。
3、算法概述
对于此题,抽象成编程问题来解决。将人、狼、羊、菜在此岸都设为1,当成功渡河后则都为0。用类bankState来表示河岸的状态,用类boatState来表示船上的状态。用time来表示运载的次数。
如此一来,问题转化成判断所有的1是不是都转化为0了,以及其中两个在一起时是否合法的问题了。
4、详细设计
按照人、狼、羊、菜的顺序描述,为了描述方便,假设在河岸A,要过河到达到河岸B。其中,人、狼、羊、菜只能为0或1,其他值都是非法的。
新建类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"); } |