import java.io.*; import java.util.*; import java.math.*; /** * Solution to Two Knights' Poem * * @author vanb */ public class twoknights_vanb { public Scanner sc; public PrintStream ps; /** Unshifted keyboard (use * for shift) */ public static final char keys[][] = { "qwertyuiop".toCharArray(), "asdfghjkl;".toCharArray(), "zxcvbnm,./".toCharArray(), "** **".toCharArray(), }; /** Shifted keyboard */ public static final char KEYS[][] = { "QWERTYUIOP".toCharArray(), "ASDFGHJKL:".toCharArray(), "ZXCVBNM<>?".toCharArray(), "** **".toCharArray(), }; /** di for knight jumps */ public static final int dis[] = { 1, 1, 2, 2, -1, -1, -2, -2 }; /** dj for knight jumps */ public static final int djs[] = { 2, -2, 1, -1, 2, -2, 1, -1 }; /** Have we seen this state before? */ public boolean seen[][][][][] = new boolean[4][10][4][10][101]; /** * Is this a legal move? * * @param i Row of new spot * @param j Column of new spot * @param c Next character of poem * @param shifted Is the other knight on a shift key? * @return true if this is a legal move, otherwise false */ public boolean canmove( int i1, int j1, int i2, int j2, char c ) { // Check that [i1,j1] is on the keyboard, is distinct from [i2,j2], // and that either this cell is a shift key, or the next character in the poem. // Remember, we're using * for shift return i1>=0 && i1<4 && j1>=0 && j1<10 && (i1!=i2 || j1!=j2) && (keys[i1][j1]=='*' || c==(keys[i2][j2]=='*'?KEYS[i1][j1]:keys[i1][j1])); } /** * Investigate moving to [i1,j1] with the other knight on [i2,j2]. * * @param i1 i coord of moving knight * @param j1 j coord of moving knight * @param i2 i coord of still knight * @param j2 j coord of still knight * @param p Position in poem * @param poem The poem itself * @return true if this moves leads to a solution, otherwise false */ public boolean investigate( int i1, int j1, int i2, int j2, int p, char poem[] ) { boolean solved = false; // Is this a legal move? if( canmove( i1, j1, i2, j2, poem[p] ) ) { // Only advance to the next character if this isn't a shift key. if( keys[i1][j1]!='*' ) ++p; // Don't go on if we've seen this state before if( !seen[i1][j1][i2][j2][p] ) { // OK, we've seen this state. seen[i1][j1][i2][j2][p] = true; // We've also seen this one, since the knights are indistinct seen[i2][j2][i1][j1][p] = true; // Go to the next level! solved = writepoem( i1, j1, i2, j2, p, poem ); } } return solved; } /** * Determine if we can write this poem from this point on. * * @param i1 i coord of first knight * @param j1 j coord of first knight * @param i2 i coord of second knight * @param j2 j coord of second knight * @param p Position in poem * @param poem The poem itself * @return true if this position leads to a solution, otherwise false */ public boolean writepoem( int i1, int j1, int i2, int j2, int p, char poem[] ) { boolean solved = false; // If we've matched all characters in the poem, then we've solved it! if( p==poem.length ) { solved = true; } else { // Go through all knight movements for( int k=0; k