问题描述
一个农夫带着一只狼、一只羊、一只白菜,身处河南岸,要把全部东西带到北岸。问题是只有一条小船,船只能容纳他和一件东西,且狼吃羊,羊吃白菜。问:农夫怎样才能将所有东西安全带到河对岸。
运行截图
算法描述
一、我们将整个过程分为在岸上,和过河两个部分。其中在岸上部分我们用一维数组currentState{X1,X2,X3,X4}表示。X1代表人,X2代表狼,X3代表羊,X4代表白菜。X1、X2、X3、X4只能取0和1。0表示在南岸,1表示在北岸。所以我们得目标是将初始状态{0,0,0,0}变为{1,1,1,1}即currentState[0]+currentState[1]+currentState[2]+currentState[3]==4,即将人、狼、羊、白菜从南岸全部运向北岸。而过河部分我们用二维数组method{X1,X2,X3,X4}表示。X1代表人,X2代表狼,X3代表羊,X4代表白菜。X1、X2、X3、X4只能取0和1。0表示不在船上,1表示在船上。
二、通过题意,我们发现currentState的取值只能为{1,1,1,1},{1,1,1,0},{1,1,0,1},{1,0,1,1},{1,0,1,0},{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,1,0,0},{0,1,0,1}这十种状态才能为安全的状态。method的取值只能为{1,1,0,0},{1,0,1,0},{1,0,0,1},{1,0,0,0}这四种方法才能过河。
三、我们用testState数组来容纳下一个可能的过河后的状态,通过
ChooseState(currentState,method[i])方法穷举下一个可能的过河后的状态,这个方法通过二进制加法来表示,即1+1=0,1+0=1,0+1=1,0+0=0。这样正好可以表示渡河后的所有状态。
四、接着我们用IsSafeState(testState)方法方法来判断testState是否为(1)中所说的安全的在岸上的状态。若不为则继续遍历方法,若为,则用DisplayState()方法打印过河的状态,并用AcceptState()方法保存testState状态为currentState状态。
五、当循环结束后,则表示遍历完成,这时输出过河成功!。
代码
public class FarmerToBridge {
static int[] testState = new int[4];//试探下一个状态
static int[] currentState = {0,0,0,0};//记录目前的状态
static int[][] method = {{1,1,0,0},{1,0,0,0},{1,0,1,0},{1,0,0,1}};//过河方法
public static void main(String[] args) {
while(currentState[0]+currentState[1]+currentState[2]+currentState[3]!=4) {//都到达北岸为止
for(int i=0;i<4;i++) {//遍历下一个状态
ChooseState(currentState,method[i]);//试探这个状态
if (IsSafeState(testState)) {//判断是否为安全状态
DisplayState();//展示这个状态
AcceptState();//接收这个状态
System.out.println("");
}
}
}
System.out.println("过河成功!");
}
public static void ChooseState(int currentState[],int method[]) {
testState[0] = (currentState[0]+method[0])%2;
testState[1] = (currentState[1]+method[1])%2;
testState[2] = (currentState[2]+method[2])%2;
testState[3] = (currentState[3]+method[3])%2;
}
public static Boolean IsSafeState(int testState[]) {
if (State(testState)) {
return true;
}else {
return false;
}
}
public static Boolean State(int testState[]) {
if ( (testState[0]==1 && testState[1]==1 && testState[2]==1 && testState[3]==1)
||(testState[0]==1 && testState[1]==1 && testState[2]==1 && testState[3]==0)
||(testState[0]==1 && testState[1]==1 && testState[2]==0 && testState[3]==1)
||(testState[0]==1 && testState[1]==0 && testState[2]==1 && testState[3]==1)
||(testState[0]==1 && testState[1]==0 && testState[2]==1 && testState[3]==0)
||(testState[0]==0 && testState[1]==0 && testState[2]==0 && testState[3]==0)
||(testState[0]==0 && testState[1]==0 && testState[2]==0 && testState[3]==1)
||(testState[0]==0 && testState[1]==0 && testState[2]==1 && testState[3]==0)
||(testState[0]==0 && testState[1]==1 && testState[2]==0 && testState[3]==0)
||(testState[0]==0 && testState[1]==1 && testState[2]==0 && testState[3]==1)
) {
return true;
}else {
return false;
}
}
public static void DisplayState() {
if(testState[0]==1) {
System.out.print("南-->北:");
}else {
System.out.print("北-->南:");
}
if (testState[0] != currentState[0]) {
System.out.print("人");
}
if (testState[1] != currentState[1]) {
System.out.print("带狼");
}
if (testState[2] != currentState[2]) {
System.out.print("带羊");
}
if (testState[3] != currentState[3]) {
System.out.print("带白菜");
}
System.out.print("过河");
}
public static void AcceptState() {
for(int j=0;j<4;j++) {
currentState[j] = testState[j];
}
}
}