魔法棋盘
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 2898 ms, 内存: 257.0 MB
// 思路:由于Java Stream不太适合这种复杂的递归和回溯问题,因此这里依然采用传统方法。
public class MagicResonanceStream {
private int n, m;
private char[][] board;
private int count = 0;
public int solve(int n, int m, String[] chessboard) {
this.n = n;
this.m = m;
this.board = new char[n][m];
for (int i = 0; i < n; i++) {
board[i] = chessboard[i].toCharArray();
}
backtrack(0, 0);
return count;
}
private void backtrack(int i, int j) {
if (i == n) {
count++;
return;
}
int ni = j == m - 1 ? i + 1 : i;
int nj = j == m - 1 ? 0 : j + 1;
if (board[i][j] == '?') {
board[i][j] = '.';
backtrack(ni, nj);
board[i][j] = 'B';
if (!hasResonance(i, j, 'B')) backtrack(ni, nj);
board[i][j] = 'R';
if (!hasResonance(i, j, 'R')) backtrack(ni, nj);
board[i][j] = '?';
} else {
if (!hasResonance(i, j, board[i][j])) backtrack(ni, nj);
}
}
private boolean hasResonance(int i, int j, char piece) {
for (int k = 0; k < n; k++) {
if (k != i && board[k][j] != '.' && board[k][j] != '?') {
if (board[k][j] != piece && Math.abs(k - i) == 2) return true;
}
}
for (int k = 0; k < m; k++) {
if (k != j && board[i][k] != '.' && board[i][k] != '?') {
if (board[i][k] != piece && Math.abs(k - j) == 2) return true;
}
}
return false;
}
public static void main(String[] args) {
MagicResonanceStream solver = new MagicResonanceStream();
System.out.println(solver.solve(3, 3, new String[]{"..R", "..B", "?R?"})); // 5
System.out.println(solver.solve(3, 3, new String[]{"?R?", "B?B", "?R?"})); // 105
}
}
解释
方法:
题解采用动态规划方法来解决问题。首先,如果列数大于行数,交换它们以简化处理。定义不同状态以表示棋盘上的可能配置,并使用一个转换字典来表明从一种状态到另一种状态的可能性。这些状态包括空格、放置黑棋、放置红棋、以及相邻位置上的不同棋子配置。使用一个二维字典dp存储每个位置的所有可能状态及其计数。遍历棋盘的每个格子,根据当前格子的内容(确定棋子、空或待定)更新dp数组。对于每个格子,考虑所有可能的棋子放置(如果当前是'?'则有三种可能),并基于前一个状态(上一个格子或上一行的结束)更新当前状态的计数。在行的开始和结束以及列的转换时需要特别处理。最后,所有在棋盘最后一个位置的状态计数之和即为答案。
时间复杂度:
O(3^(n*m))
空间复杂度:
O(3^(n*m))
代码细节讲解
🦆
动态规划解法中,状态转换字典trans是如何确保棋子之间不会产生魔法共鸣的?具体是如何定义这些状态转换的?
▷🦆
对于棋盘中的问号`?`,解法中提到可以放置空格、红棋或黑棋,这种方法是否确保了所有可能的放置情况都被考虑到了?有没有可能遗漏某些特殊的放置情况?
▷🦆
在处理棋盘的边界情况时,如何处理棋盘的第一行和第一列?特别是当棋盘的起始格子是`?`时,初始状态是如何设置的?
▷