修道士和野人

import java.util.*; 
import java.io.*;

public class MACPS 
{ 
	final public class SolutionNotFoundException extends RuntimeException 
	{
		private static final long serialVersionUID = 1L; 
	} 

	static final Object MONK = "m", // 修道士
	WILD = "c",                     // 野人
	BOAT = "v";                     // 表示船停靠的位置
	private int boat_max_load,      //船最大承载量
	boat_min_load = 1; // Shouldn't be any other value. 
	private RiverScene firstScene, finalScene; 

	// Recursively searches for a solution using Depth-First Search strategy. 
	// Takes a Stack containing only the first scene (root of tree). 
	// Returns a collection of scenes connecting the first scene to the final. 
	// Throws SolutionNotFoundException for obvious reason. 
	// Deploys the following optimization strategy: 
	// Transfers as much as possible from source side, 
	// as little as possible from target side. 
	private Collection<RiverScene> getSolutionSteps( Stack<RiverScene> takenSteps ) 
	{ 
		RiverScene lastScene = ( RiverScene ) takenSteps.peek( ); 
		if( lastScene.equals( finalScene ) ) return takenSteps; 

		RiverScene newStep = lastScene.deepCopy( ); 

		// To allow transfer in both directions to share the same chunk of code. 
		int start = boat_max_load, 
		stop = boat_min_load - 1, 
		step = -1; 
		RiverSide from = newStep.lside, 
		to = newStep.rside; 
		if( to.hasBoat( ) ) 
		{ 
			start = boat_min_load; 
			stop = boat_max_load + 1; 
			step = 1; 
			from = newStep.rside; 
			to = newStep.lside; 
		} 

		for( int nPassenger = start; nPassenger != stop; nPassenger += step ) 
		{ 
			Collection<List> menCombs = new HashSet( // HashSet eliminates duplicates. 
			Combinatorics.combinations( from.getMenList( ), nPassenger ) ); 
		
			nextComb: 
			for( Iterator comb = menCombs.iterator( ); comb.hasNext( ); ) 
			{ 
				Collection menList = ( Collection ) comb.next( ); 
				try 
				{ 
					from.transferMen( to, menList ); 
	
					// If it's a taken step, undo and try next combination. 
					for( Iterator i = takenSteps.iterator( ); i.hasNext( ); ) 
					if( i.next( ).equals( newStep ) ) 
					{ 
						to.transferMen( from, menList ); 
						continue nextComb; 
					} 
	
					takenSteps.push( newStep ); 
					return getSolutionSteps( takenSteps ); 
				} 
				catch( SecurityException e ) 
				{ 
					// Transfer didn't take place. Just try next combination. 
				} 
				catch( SolutionNotFoundException e ) 
				{ 
					// New step led to no solution in leaves. Undo, then next. 
					takenSteps.pop( ); 
					to.transferMen( from, menList ); 
				} 
			} 
		} 
		// All possible steps led to no solution, so 
		throw new SolutionNotFoundException( ); 
	} 

	// Do setup, then kick-starts getSolutionSteps( Stack takenSteps ). 
	public Collection getSolutionSteps( int nMONK, int nWILD, int boatCapacity ) 
	{ 
		if( nMONK < 0 || nWILD < 0 || boatCapacity < 0 ) 
		throw new IllegalArgumentException( "Negative argument value." ); 
	
		RiverSide sourceSide = new RiverSide( nMONK, nWILD, true ), 
		targetSide = new RiverSide( 0, 0, false ); 
		boat_max_load = boatCapacity; 
		firstScene = new RiverScene( sourceSide, targetSide ); 
		finalScene = new RiverScene( targetSide, sourceSide ); 
	
		if( firstScene.lside.fatal( ) ) // First scene can be valid but fatal. 
		throw new SolutionNotFoundException( ); 
	
		Stack steps = new Stack( ); 
		steps.push( firstScene ); 
		return getSolutionSteps( steps ); 
	} 

	public static void main( String[ ] args ) 
	{ 
		int nMONK = 3, 
		nWILD = 3, 
		boatCapacity = 2; 
	
		System.out.println( 
		"\n解决修道士和野人过河问题\n" + 
		nMONK + " 个修道士 和 " + 
		nWILD + " 个野人, " + 
		"船的承载量: " + boatCapacity ); 
	
		try
		{ 
			Collection steps = new MACPS( ). 
			getSolutionSteps( nMONK, nWILD, boatCapacity ); 
			System.out.println( "\nSolution found:\n" ); 
			for( Iterator step = steps.iterator( ); step.hasNext( ); ) 
			System.out.println( step.next( ) + "\n" ); 
		} 
		catch( SolutionNotFoundException e ) 
		{ 
			System.out.println( "\nNo solution found." ); 
		} 
	} 
} 

class RiverSide implements Serializable 
{ 
	private ArrayList men = new ArrayList( ), 
	boat = new ArrayList( ); 

	public RiverSide( int nMONK, int nWILD, boolean withBoat )
	{ 
		men.addAll( Collections.nCopies( nMONK, MACPS.MONK ) ); 
		men.addAll( Collections.nCopies( nWILD, MACPS.WILD ) ); 
		Collections.sort( men ); 
		if( withBoat ) boat.add( MACPS.BOAT ); 
	} 

	public RiverSide deepCopy( ) 
	{ 
		return ( RiverSide ) Copy.deepCopy( this ); 
	} 

	public Collection getMenList( ) 
	{ 
		return ( Collection ) Copy.deepCopy( men ); 
	} 

	public boolean equals( Object otherSide ) 
	{ 
		RiverSide other = ( RiverSide ) otherSide; 
		Collections.sort( men ); 
		Collections.sort( other.men ); 
		return this.men.equals( other.men ) && this.boat.equals( other.boat ); 
	} 

	public String toString( ) 
	{ 
		return "BOAT" + boat + "\t" + "MEN" + men; 
	} 

	public boolean hasBoat( ) 
	{ 
		return ! boat.isEmpty( ); 
	} 

	// Checks for violation of Rule #1. 
	public boolean fatal( ) 
	{ 
		int mCount = 0, cCount = 0; 
		for( Iterator i = men.iterator( ); i.hasNext( ); ) 
		{ 
			Object val = i.next( ); 
			if( val.equals( MACPS.MONK ) ) ++mCount; 
			if( val.equals( MACPS.WILD ) ) ++cCount; 
		} 
		return mCount > 0 && mCount < cCount; 
	} 

	// Throws SecurityException if the transfer of all men in menList 
	// from this to destination *will* result in violation of Rule #1. 
	// Else, executes the transfer. 
	public void transferMen( RiverSide destination, Collection menList )
	{ 
		for( Iterator i = menList.iterator( ); i.hasNext( ); ) 
		destination.men.add( men.remove( men.indexOf( i.next( ) ) ) ); 
	
		// A nice place to automate boat transfer. 
		_transferBoat( destination ); 
	
		// Undo the transfer if it led to violation of Rule #1. 
		if( fatal( ) || destination.fatal( ) )
		{ 
			destination.transferMen( this, menList ); 
			throw new SecurityException( ); 
		} 
	} 

	// Tansfers boat from this to destination. Called only by transferMen( ). 
	private void _transferBoat( RiverSide destination ) 
	{ 
		destination.boat.add( boat.remove( 0 ) ); 
	} 
} 

class RiverScene implements Serializable
{ 
	RiverSide lside, rside; // Package access. 

	public RiverScene( RiverSide lside, RiverSide rside ) 
	{ 
		this.lside = lside.deepCopy( ); 
		this.rside = rside.deepCopy( ); 
	} 

	public RiverScene deepCopy( ) 
	{ 
		return ( RiverScene ) Copy.deepCopy( this ); 
	} 

	public boolean equals( Object otherScene )
	{ 
		RiverScene other = ( RiverScene ) otherScene; 
		return lside.equals( other.lside ) && rside.equals( other.rside ); 
	} 

	public String toString( ) 
	{ 
		return "Left Side:\t" + lside + "\n" + "Right Side:\t" + rside; 
	} 
} 

class Combinatorics 
{ 
	public static Collection combinations( Collection items, int r ) 
	{ 
		if( r == 0 ) // Return [ [ ] ]. Note that [ ] denotes a List. 
			return Collections.nCopies( 1, new ArrayList( ) ); 
	
		List copy = new ArrayList( items ), // To enable subListing of items. 
		result = new ArrayList( ); 
		for( int i = 0; i < copy.size( ); ++i ) 
		{ 
			Collection subCombs = combinations( copy.subList( i + 1, copy.size( ) ), r - 1 ); 
			for( Iterator iter = subCombs.iterator( ); iter.hasNext( ); ) 
			{ 
				// Assign [ [ items.get( i ) ] ] to subComb. 
				List subComb = new ArrayList( copy.subList( i, i + 1 ) ); 
			
				subComb.addAll( ( List ) iter.next( ) ); 
				result.add( subComb ); 
			} 
		} 
		return result; 
	} 
} 

class Copy
{ 
	public static Object deepCopy( Object o ) 
	{ 
		try 
		{ 
			ByteArrayOutputStream baos = new ByteArrayOutputStream( ); 
			ObjectOutputStream oos = new ObjectOutputStream( baos ); 
			oos.writeObject( o ); 
			oos.close( ); 
		
			ObjectInputStream ois = 
			new ObjectInputStream( 
			new ByteArrayInputStream( baos.toByteArray( ) ) ); 
			return ois.readObject( ); 
		} 
		catch ( Exception e ) 
		{ 
			throw new RuntimeException( e ); 
		} 
	} 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值