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 );
}
}
}
修道士和野人
最新推荐文章于 2023-12-03 00:58:29 发布