51.N皇后(N-Queens)

题目描述

       N皇后问题研究的是,如何将 n 个皇后放置在 n×n 的棋盘上,使得两两皇后之间不能相互攻击。

       即任意两个皇后都不能处于同一行、同一列或同一斜线上


       给定一个整数 n,返回 n 皇后问题的所有解法。

       每一种解法包含了一个 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

       例如,4皇后问题有两种解法:

[
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]

解题方法

public class Solution {
    public List<List<String>> solveNQueens(int n) {
        char[][] board = new char[n][n];
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                board[i][j] = '.';
        List<List<String>> res = new ArrayList<List<String>>();
        dfs(board, 0, res);
        return res;
    }
    
    private void dfs(char[][] board, int colIndex, List<List<String>> res) {
        if(colIndex == board.length) {
            res.add(construct(board));
            return;
        }
        
        for(int i = 0; i < board.length; i++) {
            if(validate(board, i, colIndex)) {
                board[i][colIndex] = 'Q';
                dfs(board, colIndex + 1, res);
                board[i][colIndex] = '.';
            }
        }
    }
    
    private boolean validate(char[][] board, int x, int y) {
        for(int i = 0; i < board.length; i++) {
            for(int j = 0; j < y; j++) {
                if(board[i][j] == 'Q' && (x + j == y + i || x + y == i + j || x == i))
                    return false;
            }
        }
        
        return true;
    }
    
    private List<String> construct(char[][] board) {
        List<String> res = new LinkedList<String>();
        for(int i = 0; i < board.length; i++) {
            String s = new String(board[i]);
            res.add(s);
        }
        return res;
    }
}
以下使用爬山法求解n皇后问题的代码存在bug,请找出 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <vector> #include <algorithm> #include <random> using namespace std; // 显示棋盘 void print_board(int *queens, int n) { printf("\n解决方案:\n"); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (queens[i] == j) { printf("Q "); } else { printf(". "); } } printf("\n"); } } int *diag1_conflicts; int *diag2_conflicts; int pos_diag1(int row, int col) { return row + col; } int pos_diag2(int row, int col, int n) { return row - col + n - 1; } bool hill_climbing_n_queens(int n, int max_iterations) { int *queens = (int *)malloc(n * sizeof(int)); diag1_conflicts = (int *)calloc(2 * n, sizeof(int)); diag2_conflicts = (int *)calloc(2 * n, sizeof(int)); // int *col_conflicts = (int *)calloc(n, sizeof(int)); if (queens == NULL || /*col_conflicts == NULL || */ diag1_conflicts == NULL || diag2_conflicts == NULL) { printf("内存分配失败\n"); return false; } // 随机初始化并计算初始冲突 vector<int> queens_position; for (int i = 0; i < n; i++) { queens_position.push_back(i); } std::mt19937 gen(std::random_device{}()); shuffle(queens_position.begin(), queens_position.end(), gen); for (int i = 0; i < n; i++) { queens[i] = queens_position[i]; // col_conflicts[queens[i]]++; diag1_conflicts[i + queens[i]]++; diag2_conflicts[i - queens[i] + n - 1]++; } printf("使用优化爬山法求解 %d 皇后问题\n", n); for (int iter = 0; iter < max_iterations; iter++) { // 检查是否找到解 bool found_solution = true; for (int i = 0; i < n; i++) { if (/*col_conflicts[queens[i]] > 1 || */ diag1_conflicts[i + queens[i]] > 1 || diag2_conflicts[i - queens[i] + n - 1] > 1) { found_solution = false; break; } } if (found_solution) { printf("\n在第 %d 次迭代中找到解决方案!\n", iter); print_board(queens, n); free(queens); // free(col_conflicts); free(diag1_conflicts); free(diag2_conflicts); return true; } int row1_to_change = -1; int row2_to_change = -1; // 对每对相邻行的皇后,尝试互相交换 for (int row1 = 0; row1 < n; row1++) { int col1 = queens[row1]; bool isFound = false; for (int row2 = 0; row2 < n; row2++) { if (row1 == row2) { continue; } int col2 = queens[row2]; // 计算当前冲突数 int current_conflicts = diag1_conflicts[pos_diag1(row1, col1)] - 1 + diag2_conflicts[pos_diag2(row1, col1, n)] - 1 + diag1_conflicts[pos_diag1(row2, col2)] - 1 + diag2_conflicts[pos_diag2(row2, col2, n)] - 1; int new_conflicts = diag1_conflicts[pos_diag1(row2, col1)] - 1 + diag2_conflicts[pos_diag2(row2, col1, n)] - 1 + diag1_conflicts[pos_diag1(row1, col2)] - 1 + diag2_conflicts[pos_diag2(row1, col2, n)] - 1; if(new_conflicts < current_conflicts){ isFound = true; row1_to_change = row1; row2_to_change = row2; break; } } if(isFound){ break; } } // for (int row = 0; row < n - 1; row++) //{ /*int row1 = row; int row2 = row + 1; int col1 = queens[row]; int col2 = queens[row2];*/ // 计算当前冲突数 /*int current_conflicts = diag1_conflicts[pos_diag1(row1, col1)] - 1 + diag2_conflicts[pos_diag2(row1, col1, n)] - 1 + diag1_conflicts[pos_diag1(row2, col2)] - 1 + diag2_conflicts[pos_diag2(row2, col2, n)];*/ /*int current_conflicts = (diag1_conflicts[row1 + col1] - 1) + (diag2_conflicts[row1 - row + n - 1] - 1) + (diag1_conflicts[row1 + 1 +])*/ /*int current_conflicts = (diag1_conflicts[row1 + col1] - 1) + (diag2_conflicts[row2 - col2 + n - 1]) + (diag1_conflicts[row1 + col1 + 1] - 1) + (diag2_conflicts[row2 - col2 + n - 2]);*/ /*// 计算修改后的冲突数 int new_conflicts = diag1_conflicts[pos_diag1(row1 + 1, col1)] - 1 + diag2_conflicts[pos_diag2(row1 + 1, col1, n)] - 1 + diag1_conflicts[pos_diag1(row2 - 1, col2)] - 1 + diag2_conflicts[pos_diag2(row2 - 1, col2, n)]; // 计算是否保留该答案 int improvement = current_conflicts - new_conflicts; if (improvement > best_improvement) { best_improvement = improvement; best_row = row; }*/ //} /*for (int row = 0; row < n; row++) { int current_col = queens[row]; // 计算当前位置的冲突数 int current_conflicts = (col_conflicts[current_col] - 1) + (diag1_conflicts[row + current_col] - 1) + (diag2_conflicts[row - current_col + n - 1] - 1); for (int new_col = 0; new_col < n; new_col++) { if (new_col == current_col) continue; // 计算新位置的冲突数 int new_conflicts = col_conflicts[new_col] + diag1_conflicts[row + new_col] + diag2_conflicts[row - new_col + n - 1]; int improvement = current_conflicts - new_conflicts; if (improvement > best_improvement) { best_improvement = improvement; best_row = row; best_col = new_col; } } }*/ if (row1_to_change == -1) { // 随机重启 /*for (int i = 0; i < n; i++) { //col_conflicts[queens[i]]--; diag1_conflicts[i + queens[i]]--; diag2_conflicts[i - queens[i] + n - 1]--; queens[i] = rand() % n; //col_conflicts[queens[i]]++; diag1_conflicts[i + queens[i]]++; diag2_conflicts[i - queens[i] + n - 1]++; }*/ vector<int> queens_position; for (int i = 0; i < n; i++) { queens_position.push_back(i); } std::mt19937 gen(std::random_device{}()); shuffle(queens_position.begin(), queens_position.end(), gen); for (int i = 0; i < n; i++) { queens[i] = queens_position[i]; // col_conflicts[queens[i]]++; diag1_conflicts[i + queens[i]]++; diag2_conflicts[i - queens[i] + n - 1]++; } printf("迭代 %d: 随机重启\n", iter + 1); } else { // todo // 更新冲突数组并移动皇后 diag1_conflicts[pos_diag1(row1_to_change, queens[row1_to_change])]--; diag2_conflicts[pos_diag2(row1_to_change, queens[row1_to_change], n)]--; diag1_conflicts[pos_diag1(row2_to_change, queens[row2_to_change])]--; diag2_conflicts[pos_diag2(row2_to_change, queens[row2_to_change], n)]--; swap(queens[row1_to_change], queens[row2_to_change]); diag1_conflicts[pos_diag1(row1_to_change, queens[row1_to_change])]++; diag2_conflicts[pos_diag2(row1_to_change, queens[row1_to_change], n)]++; diag1_conflicts[pos_diag1(row2_to_change, queens[row2_to_change])]++; diag2_conflicts[pos_diag2(row2_to_change, queens[row2_to_change], n)]++; /*diag1_conflicts[pos_diag1(best_row, queens[best_row])]--; diag2_conflicts[pos_diag2(best_row, queens[best_row], n)]--; diag1_conflicts[pos_diag1(best_row + 1, queens[best_row + 1])]--; diag2_conflicts[pos_diag2(best_row + 1, queens[best_row + 1], n)]--; swap(queens[best_row], queens[best_row + 1]); diag1_conflicts[pos_diag1(best_row, queens[best_row])]++; diag2_conflicts[pos_diag2(best_row, queens[best_row], n)]++; diag1_conflicts[pos_diag1(best_row + 1, queens[best_row + 1])]++; diag2_conflicts[pos_diag2(best_row + 1, queens[best_row + 1], n)]++;*/ /*int old_col = queens[best_row]; //col_conflicts[old_col]--; diag1_conflicts[best_row + old_col]--; diag2_conflicts[best_row - old_col + n - 1]--; queens[best_row] = best_col;*/ // col_conflicts[best_col]++; // diag1_conflicts[best_row + best_col]++; // diag2_conflicts[best_row - best_col + n - 1]++; printf("迭代 %d: %d 与 %d行交换", iter + 1, row1_to_change, row2_to_change); } } printf("在 %d 次迭代内未找到解决方案\n", max_iterations); free(queens); // free(col_conflicts); free(diag1_conflicts); free(diag2_conflicts); return false; } int main() { int n; int max_iterations; printf("请输入皇后数量 n: "); scanf("%d", &n); printf("请输入最大迭代次数: "); scanf("%d", &max_iterations); bool result2 = hill_climbing_n_queens(n, max_iterations); return 0; }
最新发布
10-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值