1 条题解

  • 0
    @ 2026-6-19 10:31:01

    📝 题目大意

    在一个 8×88\times 8 的棋盘上,已有若干棋子(#)。每个棋子可以攻击其所在行和列的所有格子。求在空格子(.)中,有多少个位置放置新棋子后不会被任何已有棋子攻击到。

    💡 解题思路

    1. 题目分析:棋盘大小为固定 8×88\times 8,数据量极小。每个已有棋子的攻击范围是它所在的一整行和一整列。我们的棋子要安全,就必须放在一个没有任何已有棋子的行和没有任何已有棋子的列的交点上。

    2. 算法推导

      • 用一个布尔数组 f[15][15] 标记所有"危险"格子(初始全为 00)。
      • 遍历棋盘,对于每个棋子 # 所在的格子 (i,j)(i,j),将第 ii 行所有格子 f[i][k] 和第 jj 列所有格子 f[k][j] 标记为 11(危险)。
      • 最后遍历棋盘,统计 f[i][j] == 0 的格子数量,即为答案。
    3. 边界与细节

      • 棋盘上可能没有棋子(全 .),此时所有 6464 个格子都安全,答案为 6464
      • 标记危险格子时,棋子所在的格子本身也会被标记为危险,但这不影响结果,因为那个格子本身已不是空格。
      • 数组大小开到 1515 是为了避免边界判断的麻烦,直接使用 1188 的坐标。

    ⏱️ 复杂度分析

    • 时间复杂度O(8×8×8)=O(1)O(8 \times 8 \times 8) = O(1),枚举每个棋子并标记其所在行列,由于棋盘大小固定,实际为常数。
    • 空间复杂度O(1)O(1),仅需常量大小的棋盘数组。

    💻 标准代码 (C++)

    #include <bits/stdc++.h>
    using namespace std;
    
    char a[15][15];        // 存储棋盘状态
    bool f[15][15];         // 标记哪些格子会被已有棋子攻击到
    
    // 将棋子 (x,y) 所在行和列的所有格子标记为危险
    void c(int x,int y) {
    	for (int i = 1;i <= 8;i++) f[x][i] = 1;  // 标记第 x 行
    	for (int i = 1;i <= 8;i++) f[i][y] = 1;  // 标记第 y 列
    	return ;
    }
    
    int main () {
    	// 读入 8x8 棋盘
    	for (int i = 1;i <= 8;i++)
    		for (int j = 1;j <= 8;j++)
    			cin >> a[i][j];
    	// 对于每个已有棋子,标记其攻击范围
    	for (int i = 1;i <= 8;i++) 
    		for (int j = 1;j <= 8;j++) 
    			if (a[i][j] == '#') c(i,j);
    	int ans = 0;
    	// 统计未被攻击到的格子数(即安全格子)
    	for  (int i = 1;i <= 8;i++)
    		for (int j = 1;j <= 8;j++)
    			if (f[i][j] == 0) ans++;
    	printf("%d",ans);
    	return 0;
    }
    
    • 1

    信息

    ID
    840
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    3
    已通过
    3
    上传者