修道士和野人

来源:互联网 发布:c 二维数组赋值不全 编辑:程序博客网 时间:2024/04/29 00:42
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 ); } } }

0 0