为了更好的阅读体检,可以查看我的算法学习网
在线评测链接:P1064
题目内容
塔子哥是一个热衷于国际象棋的棋手,他最近在研究 n n n 皇后问题。在国际象棋中,皇后是一种强大的棋子,能够沿着横、竖、斜线攻击其他棋子。
而在 n n n 皇后问题中,皇后也是一种强大的棋子,它能攻击同一行、同一列以及同一 45 45 45 度角斜线和 135 135 135 度角斜线上的其他皇后。
塔子哥手上拿着一个 n × n n\times n n×n 的棋盘,上面已经放置了一些皇后。他希望再放置一个皇后,使得所有的皇后不会互相攻击。
对于一个 n × n n\times n n×n 的棋盘,有多种不同的摆放皇后的方式,而有些摆法可能会导致皇后之间发生攻击,有些摆法则不会。
因此,塔子哥需要找到所有满足条件的摆法,以便让他更好地研究 n n n 皇后问题,你能帮塔子哥求出有多少种放置方案吗?
输入描述
第一行输入一个正整数 n n n ,代表棋盘大小。
接下来的 n n n 行,每行输入一个仅由 $. $ 和 ∗ * ∗ 组成的字符串,其中 ∗ * ∗ 代表放置了一个皇后, . . . 代表未放置皇后。
保证输入的棋盘中没有两个皇后会互相攻击。
1 ≤ n ≤ 1000 1\le n\le 1000 1≤n≤1000
输出描述
输出塔子哥有多少种放置方案。
样例
输入
3
.*.
...
...
输出
2
思路
暴力 O ( n 3 ) O(n^3) O(n3)不可取.我们先扫描一遍棋盘。用 r , c r,c r,c 数组来统计第i行/第i列有多少个皇后。对于处于同一正副对角线的两点,有如下规律:
正对角线:两点的横纵坐标之差x-y相等.所以用x-y来对正对角线编号
副对角线:两点的横纵坐标之和相等.所以用x+y来对正对角线编号
所以再使用 x , y x,y x,y 数组来记录第i个正负对角线的皇后个数。
预处理完之后,枚举每个点 i , j i,j i,j , check一下 r [ i ] , c [ j ] , x [ i − j ] , y [ i + j ] r[i],c[j],x[i-j],y[i+j] r[i],c[j],x[i−j],y[i+j] 是不是全为0即可。 全为0就代表可行,然后计数。
最后,注意一开始局面就不合法的情况。这种情况需要输出0并提前结束程序!
代码
C++
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1005;
int a[maxn][maxn];
// 记录行,列,正负对角线的皇后个数
int c[maxn] , r[maxn] , x[maxn * 2] , y[maxn * 2];
int main()
{
int n;
cin >> n;
bool ok = true;
for (int i = 1 ; i <= n ; i++){
string t;
cin >> t;
t = '#' + t;
for (int j = 1 ; j <= n ; j++){
if (t[j] == '*'){
a[i][j] = 1;
if (r[i] || c[j] || x[i - j + n] || y[i + j]){
ok = false;
}
r[i]++;
c[j]++;
x[i - j + n]++;
y[i + j]++;
}
}
}
if (!ok){
cout << "0" << endl;
return 0;
}
int cnt = 0;
for (int i = 1 ; i <= n ; i++){
for (int j = 1 ; j <= n ; j++){
if (a[i][j] == 1) continue;
if (r[i] || c[j] || x[i - j + n] || y[i + j]) continue;
cnt ++;
}
}
cout << cnt << endl;
return 0;
}
java
import java.util.*;
public class Main{
public static void main(String args[]){
queen();
}
public static void queen(){
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
scanner.nextLine();
HashSet<Integer> row=new HashSet<>();
HashSet<Integer> col=new HashSet<>();
HashSet<Integer> dia1=new HashSet<>();
HashSet<Integer> dia2=new HashSet<>();
int c;
for(int i=0;i<n;i++){
String s=scanner.nextLine();
c=s.indexOf("*");
if(c!=-1){
row.add(i);
col.add(c);
dia1.add(i+c);
dia2.add(i-c);
}
}
int count=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(row.contains(i)||col.contains(j)||dia1.contains(i+j)||dia2.contains(i-j)){
continue;
}
count++;
}
}
System.out.println(count);
}
}
python
import sys
'''
6
.*....
......
......
.....*
......
*.....
'''
def dataProcess():
n = int(input())
grid = []
for i in range(n):
temp = input()
grid.append(list(temp))
return n,grid
# I only add one queen for next backtracing operation
def nQueen(n, grid):
c = [0] * n
r = [0] * n
x = [0] * 2 * n
y = [0] * 2 * n
a = [[0 for i in range(n)] for j in range(n)]
ans = 0
for i in range(n):
for j in range(n):
if grid[i][j] == "*":
a[i][j] = 1
r[j] += 1
c[i] += 1
x[i-j+n] += 1
y[i+j] += 1
for i in range(n):
for j in range(n):
if a[i][j] == 1:
continue
if c[i]!=0 or r[j]!=0 or x[i-j+n]!=0 or y[i+j]!=0:
continue
ans += 1
return ans
if __name__ == "__main__":
n,grid = dataProcess()
ans = nQueen(n, grid)
print(ans)
js
const lines = [];
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
(async () => {
for await (const line of rl) {
lines.push(line);
}
const n = parseInt(lines[0]);
let res = 0;
const grid = lines.slice(1).map(l => l.split(''));
const preProcessing = () => {
const col = new Map();
const row = new Map();
const diag1 = new Map();
const diag2 = new Map();
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (grid[i][j] === '*') {
col.set(j, true);
row.set(i, true);
diag1.set(i + j, true);
diag2.set(i - j, true);
}
}
}
return [col, row, diag1, diag2];
}
const [col, row, diag1, diag2] = preProcessing();
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (!(col.get(j) || row.get(i) || diag1.get(i + j) || diag2.get(i - j))) {
res += 1;
}
}
}
console.log(res);
})();
题目内容均收集自互联网,如如若此项内容侵犯了原著者的合法权益,可联系我: (CSDN网站注册用户名: 塔子哥学算法) 进行删除。