fun CharArray.getCode(direction: Boolean): Int { var result =if(direction)1else0 for(i in0 until 4){ result =(result shl3)or codeMap.findIndex(this[i], codeMap.indices) } return result }
/** 存储输入的站位 */ val rdm =CharArray(4) /** 存储目标序列 */ val dist =CharArray(8) /** 存储目标序列的方向 */ var distDirection =false /** 存储当前序列 */ val map =CharArray(8) /** 存储当前序列的方向 */ var direction =false /** 目标序列的 code */ var distCode =0
funmain(){ direction =read(map) distDirection =read(dist) distCode = dist.getCode(distDirection) for(i in0 until 4){ rdm[i]=if(map[i]=='.') map[i +4]else map[i] } if(!dfs()) print("None") }
/** 移动顺序 */ val moveOrder =charArrayOf('W','G','C') /** 标记是否为第一次找到答案 */ var nonFirst =false /** 标记指定序列是否访问过 */ val record =BooleanArray(1shl13) /** 存储路径 */ val list = LinkedList<Int>()
fundfs(): Boolean { val code = map.getCode(direction) if(record[code]||!check())returnfalse list += code // 检查当前状态是否和目标状态相同 if(code == distCode){ // 如果初始状态和目标状态相同,则直接返回 false if(list.size ==1)returnfalse if(nonFirst)println() else nonFirst =true list.forEach{print(parseCode(it))} list.removeLast() returntrue } record[code]=true val offset =if(direction)4else-4 direction =!direction // 先尝试人单独过河 val mIndex =findIndex('M', offset) map.swap(mIndex, mIndex + offset) var result =dfs() if(!result){ // 一次尝试人带一个过河 for(value in moveOrder){ val index =findIndex(value, offset) if(index !=-1){ map.swap(index, index + offset) if(dfs()) result =true map.swap(index, index + offset) } } } map.swap(mIndex, mIndex + offset) direction =!direction record[code]=false list.removeLast() return result }
funcheck(): Boolean { val offset =if(direction)-4else4 val w =findIndex('W', offset) val g =findIndex('G', offset) if(w !=-1&& g !=-1)returnfalse val c =findIndex('C', offset) return g ==-1|| c ==-1 }
/** 在指定范围内查找指定元素的下标 */ fun CharArray.findIndex(dist: Char, range: IntRange): Int { for(i in range){ if(this[i]== dist)return i } return-1 }
/** * 在指定范围的序列中查找目标下标 * @param dist 目标 * @param offset 4 表示在 [0, 4) 范围内查找,-4 表示在 [4, 8) 范围内查找 * @return 查找到返回下标,否则返回 -1 */ funfindIndex(dist: Char, offset: Int): Int { val left =if(offset ==4)0else4 return map.findIndex(dist, left until left +4) }
/** 映射表 */ val codeMap =charArrayOf('M','W','G','C','.')
/** 将指定状态哈希化 */ fun CharArray.getCode(direction: Boolean): Int { var result =if(direction)1else0 for(i in0 until 4){ result =(result shl3)or codeMap.findIndex(this[i], codeMap.indices) } return result }
/** 交换指定值 */ fun CharArray.swap(a: Int, b: Int){ this[a]=this[b].also{this[b]=this[a]} }
/** * 读取一个状态 * @return 方向,true 向右,false 向左 */ funread(map: CharArray): Boolean = with(System.`in`){ for(i in0 until 4) map[i]=read().toChar() read() val direction =read()=='-'.code skip(2) for(i in4 until 8) map[i]=read().toChar() read() direction }
staticbooleandfs(){ int code =getCode(map, direction); if(record[code]||!check())returnfalse; list.add(code); // 检查当前状态是否和目标状态相同 if(code == distCode){ // 如果初始状态和目标状态相同,则直接返回 false if(list.size()==1)returnfalse; if(nonFirst)System.out.println(); else nonFirst =true; for(int history : list){ System.out.print(parseCode(history)); } list.removeLast(); returntrue; } record[code]=true; int offset = direction ?4:-4; direction =!direction; boolean result =false; // 先尝试人单独过河 int mIndex =findIndex('M', offset); map[mIndex]='.'; map[mIndex + offset]='M'; if(dfs()) result =true; else{ // 依次尝试人带一个过河 for(char value : moveOrder){ int index =findIndex(value, offset); if(index !=-1){ map[index]='.'; map[index + offset]= value; if(dfs()) result =true; map[index]= value; map[index + offset]='.'; } } } map[mIndex]='M'; map[mIndex + offset]='.'; direction =!direction; record[code]=false; list.removeLast(); return result; }
/** 检查当前序列是否合法 */ staticbooleancheck(){ int offset = direction ?-4:4; int w =findIndex('W', offset); int g =findIndex('G', offset); if(w !=-1&& g !=-1)returnfalse; int c =findIndex('C', offset); return g ==-1|| c ==-1; }
/** 将指定状态哈希化 */ staticintgetCode(char[] map,boolean direction){ int result = direction ?1:0; for(int i =0; i !=4;++i){ result =(result <<3)|findIndex(codeMap, map[i],0, codeMap.length); } return result; }
/** * 读取一个状态 * @return 方向,true 向右,false 向左 */ staticbooleanread(char[] map)throwsIOException{ for(int i =0; i !=4;++i) map[i]=(char)System.in.read(); System.in.read(); boolean direction =System.in.read()=='-'; System.in.skip(2); for(int i =4; i !=8;++i) map[i]=(char)System.in.read(); System.in.read(); return direction; }
// 在指定范围内搜索目标下标 intfindIndex(char array[],char dist,int left,int right){ for(int i = left; i != right;++i){ if(array[i]== dist)return i; } return-1; }
// 在指定范围内查找目标下标 intfindIndex(char dist,int offset){ int left = offset ==4?0:4; returnfindIndex(map, dist, left, left +4); } // 检查当前序列是否合法 boolcheck(){ int offset = direction ?-4:4; int w =findIndex('W', offset); int g =findIndex('G', offset); if(w !=-1&& g !=-1)returnfalse; int c =findIndex('C',offset); return g ==-1|| c ==-1; }
// 映射表 char codeMap[]={'M','W','G','C','.'};
// 将指定状态哈希化 intgetCode(constchar map[],bool direction){ int result = direction ?1:0; for(int i =0; i !=4;++i){ result =(result <<3)|findIndex(codeMap, map[i],0,5); } return result; }
// 将 code 转化为字符串并打印 voidprintCode(int code){ int parse[]={ (code >>9)&7, (code >>6)&7, (code >>3)&7, code &7 }; for(constauto& value : parse){ printf("%c", codeMap[value]); } printf(" %s ",(code >>12)==0?"<-":"->"); for(int i =0; i !=4;++i){ printf("%c", parse[i]==0b100? rdm[i]:'.'); } printf("\n"); }
booldfs(){ int code =getCode(map, direction); if(record[code]||!check())returnfalse; list.push_back(code); // 检查当前状态是否和目标状态相同 if(code == distCode){ // 如果初始状态和目标状态相同,则直接返回 false if(list.size()==1)returnfalse; if(nonFirst)printf("\n"); else nonFirst =true; for(constauto& history : list){ printCode(history); } list.pop_back(); returntrue; } record[code]=true; int offset = direction ?4:-4; direction =!direction; bool result =false; // 先尝试人单独过河 int mIndex =findIndex('M', offset); swap(map[mIndex], map[mIndex + offset]); if(dfs()) result =true; else{ // 依次尝试人带一个过河 for(constauto& value : moveOrder){ int index =findIndex(value, offset); if(index !=-1){ swap(map[index], map[index + offset]); if(dfs()) result =true; swap(map[index], map[index + offset]); } } } swap(map[mIndex], map[mIndex + offset]); direction =!direction; record[code]=false; list.pop_back(); return result; }
intread(char map[]){ for(int i =0; i !=4;++i)scanf("%c", map + i); getchar(); bool direction =getchar()=='-'; scanf("%*c%*c"); for(int i =4; i !=8;++i)scanf("%c", map + i); getchar(); return direction; }
intmain(){ direction =read(map); distDirection =read(dist); distCode =getCode(dist, distDirection); for(int i =0; i !=4;++i){ rdm[i]= map[i]=='.'? map[i +4]: map[i]; } if(!dfs()) printf("None"); return0; }
/** 映射表 */ val codeMap =charArrayOf('M','W','G','C','.') /** 存储输入的站位 */ var rdm =State(0) /** 存储当前序列 */ var map =read().let{ val tmp =State(it) for(i in0 until 4){ val dist = tmp[i] rdm = rdm.set(i,if(dist =='.') tmp[i +4]else dist) } it.zipCode() } /** 存储目标序列 */ val dist =read().zipCode()
funmain(){ if(!dfs()) print("None") }
/** 移动顺序 */ var moveOrder =charArrayOf('W','G','C') /** 标记是否为第一次找到答案 */ var nonFirst =false /** 标记指定序列是否访问过 */ var record =BooleanArray(8200) /** 存储路径 */ var list = LinkedList<State>()
fundfs(): Boolean { if(record[map.value]||!map.legal)returnfalse list += map // 检查当前状态是否和目标状态相同 if(map == dist){ // 如果初始状态和目标状态相同,则直接返回 false if(list.size ==1)returnfalse if(nonFirst)println() else nonFirst =true list.forEach{print(it.toString())} list.removeLast() returntrue } record[map.value]=true map = map.flipDirection() // 先尝试人单独过河 val mIndex = map.find('M') map = map.swap(mIndex) var result =dfs() if(!result){ // 一次尝试人带一个过河 for(value in moveOrder){ val index = map.find(value) if(index !=-1){ map = map.swap(index) if(dfs()) result =true map = map.swap(index) } } } map = map.swap(mIndex).flipDirection() record[map.value]=false list.removeLast() return result }
/** 保存状态 */ @JvmInline value classState(val value: Int){
/** 获取方向 */ privateval direction: Boolean get()= value shr12==1
/** 是否合法 */ val legal: Boolean get(){ val w =find('W') val g =find('G') if(w !=-1&& g !=-1)returnfalse return g ==-1||find('C')==-1 }
/** 查找指定符号的位置 */ funfind(dist: Char): Int { for(i in0 until 4){ if(this[i,!direction]== dist)return i } return-1 }
/** 翻转方向 */ funflipDirection(): State =State( if(direction) value and1.shl(12).inv()else value or1.shl(12) )
/** 交换指定值 */ funswap(count: Int): State =set(count,getOpposite(count))
/** * 设置指定位置上的符号 * @param count 下标(从右往左,从 0 开始递增) * @param dist 要设置的符号 */ funset(count: Int, dist: Char): State { val code = codeMap.indexOf(dist) val base = count *3 var result = value for(i in0 until 3){ val bit =(code shr i)and1 val tmp =1.shl(base + i) result =if(bit ==0) result and tmp.inv()else result or tmp } returnState(result) }
/** 将状态码压缩到 13bit,存储左侧数据 */ fun Int.zipCode(): State =State((this.shr(12)and0xFFF)or(thisshr24).shl(12))
/** * 读取一个状态 * @return 第 25 位表示方向 1 为右,0 为左,然后从最高位到最低位依次存储输入,一位输入占 3bit */ funread(): Int = with(System.`in`){ var result =0 for(i in0 until 4){ result =(result shl3)or codeMap.indexOf(read().toChar()) } read() val direction =read()=='-'.code skip(2) for(i in0 until 4){ result =(result shl3)or codeMap.indexOf(read().toChar()) } read() if(direction) result = result or(1shl24) result }