华为OD机试-围棋的气-数组(Java 2024 D卷 100分)

题目描述

围棋棋盘由纵横各19条线垂直相交组成,棋盘上一共19x19=361个交点。对弈双方一方执白棋,一方执黑棋,落子时只能将棋子置于交点上。

“气”是围棋中很重要的一个概念,某个棋子有几口气,是指其上下左右方向四个相邻的交叉点中,有几个交叉点没有棋子。在棋盘的边缘上的棋子最多有3口气,在棋盘角点的棋子最多有2口气,其它情况最多有4口气。

所有同色棋子的气之和叫作该色棋子的气。需要注意的是,同色棋子重合的气点,对于该颜色棋子来说,只能计算一次气。

输入描述

输入包括两行数据,每行数据以空格分隔,数据个数是2的整数倍,每两个数是一组,代表棋子在棋盘上的坐标。坐标的原点在棋盘左上角点,第一个值是行号,范围从0到18;第二个值是列号,范围从0到18。第一行表示黑棋的坐标,第二行表示白棋的坐标。

输出描述

输出两个数字,以空格分隔,第一个数代表黑棋的气数,第二个数代表白棋的气数。

示例

输入:

0 5 8 9 9 10
5 0 9 9 9 8

输出:

8 7

解题思路

  1. 初始化棋盘: 创建一个19x19的棋盘,用于记录黑棋和白棋的位置。
  2. 记录棋子位置: 根据输入,将黑棋和白棋的位置记录在棋盘上。
  3. 计算气数: 对于每个棋子,检查其上下左右四个方向的相邻点,如果该点为空且未被计算过,则计入气数。
  4. 输出结果: 输出黑棋和白棋的总气数。

代码实现

Java
import java.util.*;

public class Solution {
    private static final int SIZE = 19;
    private static final int[][] DIRECTIONS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] blackInput = scanner.nextLine().split(" ");
        String[] whiteInput = scanner.nextLine().split(" ");

        Set<String> blackStones = new HashSet<>();
        Set<String> whiteStones = new HashSet<>();

        for (int i = 0; i < blackInput.length; i += 2) {
            int x = Integer.parseInt(blackInput[i]);
            int y = Integer.parseInt(blackInput[i + 1]);
            blackStones.add(x + "," + y);
        }

        for (int i = 0; i < whiteInput.length; i += 2) {
            int x = Integer.parseInt(whiteInput[i]);
            int y = Integer.parseInt(whiteInput[i + 1]);
            whiteStones.add(x + "," + y);
        }

        int blackLiberties = calculateLiberties(blackStones, whiteStones);
        int whiteLiberties = calculateLiberties(whiteStones, blackStones);

        System.out.println(blackLiberties + " " + whiteLiberties);
    }

    private static int calculateLiberties(Set<String> stones, Set<String> opponentStones) {
        Set<String> liberties = new HashSet<>();
        for (String stone : stones) {
            String[] parts = stone.split(",");
            int x = Integer.parseInt(parts[0]);
            int y = Integer.parseInt(parts[1]);
            for (int[] dir : DIRECTIONS) {
                int nx = x + dir[0];
                int ny = y + dir[1];
                if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE) {
                    String pos = nx + "," + ny;
                    if (!stones.contains(pos) && !opponentStones.contains(pos)) {
                        liberties.add(pos);
                    }
                }
            }
        }
        return liberties.size();
    }
}
Python
SIZE = 19
DIRECTIONS = [(-1, 0), (1, 0), (0, -1), (0, 1)]

def calculate_liberties(stones, opponent_stones):
    liberties = set()
    for stone in stones:
        x, y = map(int, stone.split(','))
        for dx, dy in DIRECTIONS:
            nx, ny = x + dx, y + dy
            if 0 <= nx < SIZE and 0 <= ny < SIZE:
                pos = f"{nx},{ny}"
                if pos not in stones and pos not in opponent_stones:
                    liberties.add(pos)
    return len(liberties)

black_input = input().split()
white_input = input().split()

black_stones = set()
white_stones = set()

for i in range(0, len(black_input), 2):
    x, y = int(black_input[i]), int(black_input[i + 1])
    black_stones.add(f"{x},{y}")

for i in range(0, len(white_input), 2):
    x, y = int(white_input[i]), int(white_input[i + 1])
    white_stones.add(f"{x},{y}")

black_liberties = calculate_liberties(black_stones, white_stones)
white_liberties = calculate_liberties(white_stones, black_stones)

print(black_liberties, white_liberties)
C++
#include <iostream>
#include <vector>
#include <set>
#include <sstream>

using namespace std;

const int SIZE = 19;
const int DIRECTIONS[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

int calculateLiberties(const set<string>& stones, const set<string>& opponentStones) {
    set<string> liberties;
    for (const auto& stone : stones) {
        int x, y;
        char comma;
        istringstream iss(stone);
        iss >> x >> comma >> y;
        for (const auto& dir : DIRECTIONS) {
            int nx = x + dir[0];
            int ny = y + dir[1];
            if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE) {
                string pos = to_string(nx) + "," + to_string(ny);
                if (stones.find(pos) == stones.end() && opponentStones.find(pos) == opponentStones.end()) {
                    liberties.insert(pos);
                }
            }
        }
    }
    return liberties.size();
}

int main() {
    string blackInput, whiteInput;
    getline(cin, blackInput);
    getline(cin, whiteInput);

    set<string> blackStones, whiteStones;
    istringstream blackIss(blackInput), whiteIss(whiteInput);
    int x, y;
    while (blackIss >> x >> y) {
        blackStones.insert(to_string(x) + "," + to_string(y));
    }
    while (whiteIss >> x >> y) {
        whiteStones.insert(to_string(x) + "," + to_string(y));
    }

    int blackLiberties = calculateLiberties(blackStones, whiteStones);
    int whiteLiberties = calculateLiberties(whiteStones, blackStones);

    cout << blackLiberties << " " << whiteLiberties << endl;
    return 0;
}
JavaScript
const SIZE = 19;
const DIRECTIONS = [[-1, 0], [1, 0], [0, -1], [0, 1]];

function calculateLiberties(stones, opponentStones) {
    const liberties = new Set();
    stones.forEach(stone => {
        const [x, y] = stone.split(',').map(Number);
        DIRECTIONS.forEach(([dx, dy]) => {
            const nx = x + dx;
            const ny = y + dy;
            if (nx >= 0 && nx < SIZE && ny >= 0 && ny < SIZE) {
                const pos = `${nx},${ny}`;
                if (!stones.has(pos) && !opponentStones.has(pos)) {
                    liberties.add(pos);
                }
            }
        });
    });
    return liberties.size;
}

const blackInput = prompt("Enter black stones:").split(' ');
const whiteInput = prompt("Enter white stones:").split(' ');

const blackStones = new Set();
const whiteStones = new Set();

for (let i = 0; i < blackInput.length; i += 2) {
    const x = parseInt(blackInput[i]);
    const y = parseInt(blackInput[i + 1]);
    blackStones.add(`${x},${y}`);
}

for (let i = 0; i < whiteInput.length; i += 2) {
    const x = parseInt(whiteInput[i]);
    const y = parseInt(whiteInput[i + 1]);
    whiteStones.add(`${x},${y}`);
}

const blackLiberties = calculateLiberties(blackStones, whiteStones);
const whiteLiberties = calculateLiberties(whiteStones, blackStones);

console.log(blackLiberties, whiteLiberties);

复杂度分析

  • 时间复杂度: O(n),其中 n 是棋子的数量。每个棋子的四个方向都需要检查。
  • 空间复杂度: O(n),用于存储棋子和气的位置。

总结

通过记录棋子的位置并检查其相邻点,我们可以有效地计算黑棋和白棋的气数。不同语言的实现方式略有不同,但核心思路一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝白咖啡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值