void Solve() { for(int i=0;i<=15;i++) { for(int j=0;j<4;j++) { rect[j].width=r[j].width; rect[j].height=r[j].height; } for(int j=0;j<4;j++) { if(i&(1<<j)) { swap(rect[j].width,rect[j].height); } } Solve1(), Solve2(), Solve3(); } }
int Solver::Search1(int twist, int flip, int choice, int depth) { int cost, totalCost; int move; int power; int twist2, flip2, choice2; int result; // Compute cost estimate to phase 1 goal state cost = Phase1Cost(twist, flip, choice); // h if (cost == 0) // Phase 1 solution found... { solutionLength1 = depth; // Save phase 1 solution length // We need an appropriately initialized cube in order // to begin phase 2. First, create a new cube that // is a copy of the initial scrambled cube. Then we // apply the phase 1 move sequence to that cube. The // phase 2 search can then determine the initial // phase 2 coordinates (corner, edge, and slice // permutation) from this cube. // // Note: No attempt is made to merge moves of the same // face adjacent to the phase 1 & phase 2 boundary since // the shorter sequence will quickly be found. KociembaCube phase2Cube = cube; for (int i = 0; i < solutionLength1; i++) { for (power = 0; power < solutionPowers1[i]; power++) phase2Cube.ApplyMove(solutionMoves1[i]); } // Invoke Phase 2 (void)Solve2(phase2Cube); } // See if node should be expanded totalCost = depth + cost; // g + h if (totalCost <= threshold1) // Expand node { // If this happens, we should have found the // optimal solution at this point, so we // can exit indicating such. Note: the first // complete solution found in phase1 is optimal // due to it being an addmissible IDA* search. if (depth >= minSolutionLength-1 || minSolutionLength < 24) return OPTIMUM_FOUND; for (move = Cube::Move::R; move <= Cube::Move::B; move++) { if (Disallowed(move, solutionMoves1, depth)) continue; twist2 = twist; flip2 = flip; choice2 = choice; solutionMoves1[depth] = move; for (power = 1; power < 4; power++) { solutionPowers1[depth] = power; twist2 = twistMoveTable[twist2][move]; flip2 = flipMoveTable[flip2][move]; choice2 = choiceMoveTable[choice2][move]; nodes1++; // Apply the move if (result = Search1(twist2, flip2, choice2, depth+1)) return result; } } } else // Maintain minimum cost exceeding threshold { if (totalCost < newThreshold1) newThreshold1 = totalCost; } return NOT_FOUND; }
int Solver::Search1(int twist, int flip, int choice, int depth) { int cost, totalCost; int move; int power; int twist2, flip2, choice2; int result; cost = Phase1Cost(twist, flip, choice); if (cost == 0) { solutionLength1 = depth; KociembaCube phase2Cube = cube; for (int i = 0; i < solutionLength1; i++) { for (power = 0; power < solutionPowers1[i]; power++) phase2Cube.ApplyMove(solutionMoves1[i]); } (void)Solve2(phase2Cube); if(stopped) return ABORT; } totalCost = depth + cost; if (totalCost <= threshold1) { if (depth >= minSolutionLength-1) return OPTIMUM_FOUND; for (move = Cube::R; move <= Cube::B; move++) { if (Disallowed(move, solutionMoves1, depth)) continue; twist2 = twist; flip2 = flip; choice2 = choice; solutionMoves1[depth] = move; for (power = 1; power < 4; power++) { solutionPowers1[depth] = power; twist2 = twistMoveTable[twist2][move]; flip2 = flipMoveTable[flip2][move]; choice2 = choiceMoveTable[choice2][move]; if ((result = Search1(twist2, flip2, choice2, depth+1))) return result; } } } else { if (totalCost < newThreshold1) newThreshold1 = totalCost; } return NOT_FOUND; }