// 亚马逊棋(Amazons)蒙特卡洛AI程序 - 优化版 #include #include #include #include #include #include #include #include #include #include #include // 添加memset #define GRIDSIZE 8 #define OBSTACLE 2 #define judge_black 0 #define judge_white 1 #define grid_black 1 #define grid_white -1 using namespace std; // 均衡型参数配置 const double CONTROL_FACTOR = 1.0; const double SAFETY_FACTOR = 1.0; const double SURROUND_FACTOR = 10.0; const double CENTER_FACTOR = 1.0; // 蒙特卡洛参数 - 减少模拟次数提高速度 const int SIMULATIONS_PER_MOVE = 15; // 减少模拟次数 const int MAX_SIMULATION_STEPS = 5; // 减少模拟步数 const int MCTS_ITERATIONS = 50; // 减少迭代次数 // 预计算方向向量 const int dx[8] = { -1, -1, -1, 0, 0, 1, 1, 1 }; const int dy[8] = { -1, 0, 1, -1, 1, -1, 0, 1 }; int currBotColor; int gridInfo[GRIDSIZE][GRIDSIZE] = { 0 }; // 随机数生成器 static mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); // 走法结构体 - 紧凑表示 struct Move { unsigned char x0, y0, x1, y1, x2, y2; Move(int x0=0, int y0=0, int x1=0, int y1=0, int x2=0, int y2=0) : x0(x0), y0(y0), x1(x1), y1(y1), x2(x2), y2(y2) {} bool isValid() const { return x0 != 255; } }; // 移动缓存结构 struct MoveCache { int pieceX, pieceY; int moveCount; int moves[56]; // 最大可能移动数:8个方向 * 7步 = 56 MoveCache() : pieceX(-1), pieceY(-1), moveCount(0) { memset(moves, 0, sizeof(moves)); } }; // 预计算中心距离 const double centerDistance[GRIDSIZE][GRIDSIZE] = { {9.90, 8.96, 8.06, 7.28, 7.28, 8.06, 8.96, 9.90}, {8.96, 7.07, 6.10, 5.39, 5.39, 6.10, 7.07, 8.96}, {8.06, 6.10, 4.95, 4.03, 4.03, 4.95, 6.10, 8.06}, {7.28, 5.39, 4.03, 2.12, 2.12, 4.03, 5.39, 7.28}, {7.28, 5.39, 4.03, 2.12, 2.12, 4.03, 5.39, 7.28}, {8.06, 6.10, 4.95, 4.03, 4.03, 4.95, 6.10, 8.06}, {8.96, 7.07, 6.10, 5.39, 5.39, 6.10, 7.07, 8.96}, {9.90, 8.96, 8.06, 7.28, 7.28, 8.06, 8.96, 9.90} }; // 全局移动列表缓存 vector allPossibleMoves; vector moveCache[2]; // 0:黑方, 1:白方 inline bool inMap(int x, int y) { return (unsigned)x < GRIDSIZE && (unsigned)y < GRIDSIZE; } // 快速棋盘复制(使用memcpy) inline void copyBoard(const int src[GRIDSIZE][GRIDSIZE], int dst[GRIDSIZE][GRIDSIZE]) { memcpy(dst, src, sizeof(int) * GRIDSIZE * GRIDSIZE); } bool ProcStep(int x0, int y0, int x1, int y1, int x2, int y2, int color, bool check_only) { if (!inMap(x0, y0) || !inMap(x1, y1) || !inMap(x2, y2)) return false; if (gridInfo[x0][y0] != color || gridInfo[x1][y1] != 0) return false; if (gridInfo[x2][y2] != 0 && !(x2 == x0 && y2 == y0)) return false; if (!check_only) { gridInfo[x0][y0] = 0; gridInfo[x1][y1] = color; gridInfo[x2][y2] = OBSTACLE; } return true; } // 计算棋子的所有移动位置(优化版) void calculateMovesFast(const int grid[GRIDSIZE][GRIDSIZE], int x, int y, int moves[], int &count) { count = 0; int color = grid[x][y]; if (color == 0) return; for (int d = 0; d < 8; ++d) { for (int step = 1; step < GRIDSIZE; ++step) { int xx = x + dx[d] * step; int yy = y + dy[d] * step; if (!inMap(xx, yy) || grid[xx][yy] != 0) break; moves[count++] = (xx << 3) | yy; // 使用位运算压缩坐标 } } } // 预先计算所有棋子的移动 void precalculateMoves(const int grid[GRIDSIZE][GRIDSIZE], int color) { int idx = (color == grid_black) ? 0 : 1; moveCache[idx].clear(); for (int i = 0; i < GRIDSIZE; ++i) { for (int j = 0; j < GRIDSIZE; ++j) { if (grid[i][j] == color) { MoveCache mc; mc.pieceX = i; mc.pieceY = j; calculateMovesFast(grid, i, j, mc.moves, mc.moveCount); if (mc.moveCount > 0) { moveCache[idx].push_back(mc); } } } } } // 获取所有可能的走法(使用缓存) vector getAllPossibleMovesFast(const int grid[GRIDSIZE][GRIDSIZE], int color) { vector moves; int idx = (color == grid_black) ? 0 : 1; // 如果缓存未计算,先计算 if (moveCache[idx].empty()) { precalculateMoves(grid, color); } // 临时棋盘用于计算箭的位置 int tempGrid[GRIDSIZE][GRIDSIZE]; for (const auto& piece : moveCache[idx]) { for (int m = 0; m < piece.moveCount; ++m) { int movePos = piece.moves[m]; int moveX = movePos >> 3; int moveY = movePos & 7; // 创建临时棋盘 copyBoard(grid, tempGrid); tempGrid[moveX][moveY] = color; tempGrid[piece.pieceX][piece.pieceY] = 0; // 计算箭的位置 int arrowMoves[56]; int arrowCount = 0; calculateMovesFast(tempGrid, moveX, moveY, arrowMoves, arrowCount); for (int a = 0; a < arrowCount; ++a) { int arrowPos = arrowMoves[a]; int arrowX = arrowPos >> 3; int arrowY = arrowPos & 7; moves.push_back(Move(piece.pieceX, piece.pieceY, moveX, moveY, arrowX, arrowY)); } } } return moves; } // 快速局面评估(简化版) double evaluateBoardFast(const int grid[GRIDSIZE][GRIDSIZE], int originalColor) { double score = 0.0; // 快速评估:只计算移动能力和中心控制 for (int i = 0; i < GRIDSIZE; ++i) { for (int j = 0; j < GRIDSIZE; ++j) { int piece = grid[i][j]; if (piece != 0 && piece != OBSTACLE) { // 中心控制 double centerValue = (10.0 - centerDistance[i][j]) * CENTER_FACTOR; // 移动能力(简化计算) int moves[56]; int moveCount = 0; calculateMovesFast(grid, i, j, moves, moveCount); double mobility = moveCount * CONTROL_FACTOR; if (piece == originalColor) { score += centerValue + mobility; } else { score -= centerValue + mobility; } } } } // 归一化 return tanh(score / 50.0); } // 优化的随机游戏模拟 double simulateRandomGameFast(Move move, const int originalGrid[GRIDSIZE][GRIDSIZE], int color) { // 使用栈上数组,避免动态分配 int simGrid[GRIDSIZE][GRIDSIZE]; copyBoard(originalGrid, simGrid); // 执行第一步 simGrid[move.x1][move.y1] = color; simGrid[move.x0][move.y0] = 0; simGrid[move.x2][move.y2] = OBSTACLE; int currentColor = -color; int steps = 0; // 快速随机模拟 while (steps < MAX_SIMULATION_STEPS) { // 获取当前玩家的移动 int moves[56]; int moveCount = 0; bool hasMove = false; // 找到一个可以移动的棋子 for (int i = 0; i < GRIDSIZE && !hasMove; ++i) { for (int j = 0; j < GRIDSIZE && !hasMove; ++j) { if (simGrid[i][j] == currentColor) { calculateMovesFast(simGrid, i, j, moves, moveCount); if (moveCount > 0) { // 随机选择一个移动 int moveIdx = rng() % moveCount; int movePos = moves[moveIdx]; int moveX = movePos >> 3; int moveY = movePos & 7; // 计算箭的位置 int arrowMoves[56]; int arrowCount = 0; // 临时棋盘计算箭 int tempGrid[GRIDSIZE][GRIDSIZE]; copyBoard(simGrid, tempGrid); tempGrid[moveX][moveY] = currentColor; tempGrid[i][j] = 0; calculateMovesFast(tempGrid, moveX, moveY, arrowMoves, arrowCount); if (arrowCount > 0) { int arrowIdx = rng() % arrowCount; int arrowPos = arrowMoves[arrowIdx]; int arrowX = arrowPos >> 3; int arrowY = arrowPos & 7; // 执行移动 simGrid[moveX][moveY] = currentColor; simGrid[i][j] = 0; simGrid[arrowX][arrowY] = OBSTACLE; hasMove = true; } } } } } if (!hasMove) break; currentColor = -currentColor; steps++; } return evaluateBoardFast(simGrid, color); } // 主决策函数 Move findBestMoveWithMonteCarlo() { // 清空缓存 moveCache[0].clear(); moveCache[1].clear(); // 获取所有可能走法 vector moves = getAllPossibleMovesFast(gridInfo, currBotColor); if (moves.empty()) { return Move(255, 255, 255, 255, 255, 255); } // 如果走法很少,直接返回第一个 if (moves.size() == 1) { return moves[0]; } Move bestMove = moves[0]; double bestScore = -1e9; // 限制检查的走法数量 int checkCount = min((int)moves.size(), 30); // 均匀采样,而不是检查所有走法 vector indices(moves.size()); for (int i = 0; i < moves.size(); ++i) indices[i] = i; shuffle(indices.begin(), indices.end(), rng); for (int i = 0; i < checkCount; ++i) { int idx = indices[i]; double totalScore = 0.0; // 减少模拟次数 int sims = (i < 10) ? SIMULATIONS_PER_MOVE : (SIMULATIONS_PER_MOVE / 2); for (int sim = 0; sim < sims; ++sim) { totalScore += simulateRandomGameFast(moves[idx], gridInfo, currBotColor); } double avgScore = totalScore / sims; if (avgScore > bestScore) { bestScore = avgScore; bestMove = moves[idx]; } } return bestMove; } int main() { ios::sync_with_stdio(false); cin.tie(0); // 快速初始化棋盘 memset(gridInfo, 0, sizeof(gridInfo)); gridInfo[0][2] = gridInfo[2][0] = gridInfo[5][0] = gridInfo[7][2] = grid_black; gridInfo[0][5] = gridInfo[2][7] = gridInfo[5][7] = gridInfo[7][5] = grid_white; int turnID; cin >> turnID; currBotColor = grid_white; for (int i = 0; i < turnID; i++) { int x0, y0, x1, y1, x2, y2; cin >> x0 >> y0 >> x1 >> y1 >> x2 >> y2; if (x0 == -1) { currBotColor = grid_black; } else if (x0 >= 0) { ProcStep(x0, y0, x1, y1, x2, y2, -currBotColor, false); } if (i < turnID - 1) { cin >> x0 >> y0 >> x1 >> y1 >> x2 >> y2; if (x0 >= 0) { ProcStep(x0, y0, x1, y1, x2, y2, currBotColor, false); } } } // 决策 Move bestMove = findBestMoveWithMonteCarlo(); // 如果无效,使用简单策略 if (!bestMove.isValid()) { // 简单策略:找到第一个合法走法 vector moves = getAllPossibleMovesFast(gridInfo, currBotColor); if (!moves.empty()) { bestMove = moves[0]; } } cout << (int)bestMove.x0 << ' ' << (int)bestMove.y0 << ' ' << (int)bestMove.x1 << ' ' << (int)bestMove.y1 << ' ' << (int)bestMove.x2 << ' ' << (int)bestMove.y2 << endl; return 0; }