Missionaries and Cannibals problem breadth first search implementation

11 篇文章 0 订阅

Problem description:

   Three missionaries and cannibals want to cross the river using a boat which can carry at most two people, under the constraint that, for both banks, if there are missionries present on the bank, they can't be outnumbered by cannibals (if they were, the cannibals would eat the missionaries.) The boat cannot cross the river by itself with no people on board.

Problem solution:

   This kinds of problem has many solutions. All the solustion are all about state space search. For this problem the state represent is very important. The problem's state can be represented as three element tuple (M, C, B).

–M: number of missionaries on left bank
–C:  number of cannibals on left bank
–B:   number of boat on left bank 
 
   The state can be a six element tuple the left bank state and right bank state, because we can deduce the right bank state by left bank state, so the three left bank element tupe is enough. The start state is (3, 3, 1) which mean all the missionaries, cannibals and boat on the left side bank. The end state is (0, 0, 0) which means all the missionaries, cannibals and boat on the right bank. To find a path from the state space tree, we should skip or prune some invalid branches or nodes.
 
   When generate the successive states, some states are not allowed except the below operation to get successive states.
 
1.Move one cannibal across the river.
2.Move two cannibals across the river.
3.Move one missionary across the river.
4.Move two missionaries across the river.
5.Move one missionary and one cannibal.
 
Below is an implementation with breadth first search. Some other methods I will study later.
 
 
package hello.test;


import java.util.LinkedList;
import java.util.Queue;

public class MCB3 {
	// the state queue used for search
	private Queue<State> q = new LinkedList<State>();
	
	// State class 
	private class State {
		private int missionary;  // the number of  missionaries between 0 and 3
		private int cannibals;	// the number of cannibals between 0 and 3
		private int boat;	// the number of boat between 0 and 1
		private State previous;	// the previous state used to record the state transfer path
		private int stateLevel;	// state level used to record the height of the tree
		
		// constructor
		public State(int missionary, int cannibals, int boat, int stateLevel) {
			this(missionary, cannibals, boat, null, stateLevel);
		}
		
		// constructor
		public State(int missionary, int cannibals, int boat, State preState, int stateLevel) {
			this.missionary = missionary;
			this.cannibals = cannibals;
			this.boat = boat;
			this.previous = preState;
			this.stateLevel = stateLevel;
		}
		
		// get the state level
		public int getStateLevel() {
			return this.stateLevel;
		}
		
		// is the state a valid state
		public boolean isValid() {
			if (missionary < 0 || missionary > 3 || cannibals < 0 || cannibals > 3) return false;
			if(3 - missionary < 0 || 3 - missionary > 3 || 3 - cannibals < 0 || 3 - cannibals > 3) return false;
			if(missionary > 0 && cannibals > missionary) return false;
			if(3 - missionary > 0 && 3 - cannibals > 3 - missionary) return false;
			return true;
		}
		
		// is two states equal to each other
		public boolean isEqual(State s) {
			return (s.missionary == this.missionary && 
					s.cannibals == this.cannibals &&
					s.boat == this.boat);
		}
		
		// is the state is the goal state
		public boolean isGoal() {
			State goal = new State(0, 0, 0, 99999);
			return isEqual(goal);
		}
		
		// print the path
		public void print() {
			if(this.previous != null) {
				this.previous.print();
			}
			
			String side = this.boat == 1 ? " Boat Right -> " : " <- Boat Left ";
			System.out.println(this.missionary + "M/" + this.cannibals + "C " + side + "" + 
			(3 - this.missionary) + "M/" + (3 - this.cannibals) + "C");
		}
	}
	
	// expand the successors from the current state and enqueue these successor states
	private void successors(State currentState) {
		for(int i = 0; i <= 2; i++) {
			for(int j = 0; j <= 2; j++) {
				if(i == 0 && j == 0) continue;
				if(i + j > 2) break;
				addStatetoQueue(currentState, i, j);
			}
		}
	}
	
	// generate a new state and enqueue the state
	private void addStatetoQueue(State preState, int missionary, int cannibal) {
		// TODO Auto-generated method stub
		int side = preState.boat == 1 ? -1 : 1;
		State state = new State(preState.missionary + side * missionary, 
				preState.cannibals + side * cannibal, 1 - preState.boat, preState,
				preState.getStateLevel() + 1);
		if(state.isValid())
			q.add(state);
	}
	
	// solve the mcb problem with bfs
	public void solve() {
		//ArrayList<State> solutions = new ArrayList<State>();
		boolean isFirstFound = false;	// is the state first time found
		boolean isallFound = false;	// is all the states found
		int optimalLevel = 0;	// the state level
		int count = 0;	// solution count
		
		State start = new State(3, 3, 1, 1);	// start state
		q.add(start);
		
		while(!q.isEmpty() && !isallFound) {
			State current = q.remove();
			
			if(current.isGoal()) {
				if(isFirstFound) {
					if(current.getStateLevel() <= optimalLevel) {
						count++;
						System.out.println("The "+ count + "th solution ===");
						current.print();
						System.out.println();
					} else {
						isallFound = true;
					}
				} else {
					isFirstFound = true;
					optimalLevel = current.getStateLevel();
					count++;
					System.out.println("The "+ count + "th solution, the level is " + optimalLevel + " ======" );
					current.print();
					System.out.println();
				}
				
			} else {
				successors(current);
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MCB3 mcb = new MCB3();
		mcb.solve();
	}

}



 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值