华为机考真题 -- 围棋气之统计

题目描述:

围棋棋盘由纵横各19条线垂直相交组成,棋盘上一共19x19=361个交点,对弈双方一方执白棋,一方执黑棋,落子时只能将棋子置于交点上。"气"是围棋中很重要的一个概念,某个棋子有几口气,是指其上下左右方向四个相邻的交叉点中,有几个交叉点没有棋子,由此可知:1、在棋盘的边缘上的棋子最多有3口气(黑1),在棋盘角点的棋子最多有2口气(黑2),其它情况最多有4口气(白1);2、所有同色棋子的气之和叫作该色棋子的气,需要注意的是,同色棋子重合的气点,对于该颜色棋子来说,只能计算一次气,比如下图中,黑棋一共4口气,而不是5口气,因为黑1和黑2中间红色三角标出的气是两个黑棋共有的,对于黑棋整体来说只能算一个气。3、本题目只计算气,对于眼也按气计算,如果您不清楚"眼"的概念,可忽略,按照前面描述的规则计算即可现在,请根据输入的黑棋和白棋的坐标位置,计算黑棋和白起一共各有多少气?

输入描述:

输入包括两行数据,如:

0 5 8 9 9 10

5 0 9 9 9 8

1、每行数据以空格分隔,数据个数是2的整数倍,每两个数是一组,代表棋子在棋盘上的坐标;

2、坐标的原点在棋盘左上角点,第一个值是行号,范围从0到18;第二个值是列号,范围从0到18;

3、举例说明: 第一行数据表示三个坐标 (0,5)、 (8,9)、 (9,10);

4、第一行表示黑棋的坐标,第二行表示白棋的坐标。

5、题目保证输入两行数据,无空行且每行按前文要求是偶数个,每个坐标不会超出棋盘范围。

输出描述:

8 7

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

C++源码:

cpp 复制代码
#include <iostream>
#include <string>
#include <ctime>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <sstream>

using namespace std;

const int BOARD_SIZE = 19;

// 计算单个棋子的气数,不考虑同色棋子的共享气点
int rawCountLiberties(int x, int y) {
    int liberties = 4; // 中心位置的初始气数
    if (x == 0 || x == BOARD_SIZE - 1) liberties--; // 边缘减少1气
    if (y == 0 || y == BOARD_SIZE - 1) liberties--;
    if ((x == 0 || x == BOARD_SIZE - 1) && (y == 0 || y == BOARD_SIZE - 1)) liberties--; // 角落减少额外1气
    return liberties;
}


// 计算所有同色棋子共享考虑后的气数,使用map代替unordered_map

int countSharedLiberties(const vector<pair<int, int>>& positions) {

    map<pair<int, int>, int> sharedSpaces;

    // 遍历所有棋子位置,记录每个潜在气点出现的次数
    for (const auto& pos : positions) {
        for (int dx = -1; dx <= 1; dx++) {
            for (int dy = -1; dy <= 1; dy++) {
                if (dx == 0 && dy == 0) continue; // 排除自身
                int newX = pos.first + dx;
                int newY = pos.second + dy;
                if (newX >= 0 && newX < BOARD_SIZE && newY >= 0 && newY < BOARD_SIZE) {
                    sharedSpaces[{newX, newY}]++;
                }
            }
        }
    }

    // 计算实际气数,去除共享的气点
    int totalLiberties = 0;
    for (const auto& space : sharedSpaces) {
        if (space.second == 1) { // 只有当该点周围只有一个同色棋子时才计入气数
            totalLiberties++;
        }
    }
    return totalLiberties;
}

// 解析输入的坐标字符串,转换为pair<int, int>的vector
vector<pair<int, int>> parseCoordinates(const string& input) {
    vector<pair<int, int>> coordinates;
    stringstream ss(input);
    int x, y;
    while (ss >> x >> y) {
        coordinates.emplace_back(x, y); // 直接读取两个整数作为坐标
    }
    return coordinates;
}

int main() {

    string blackInput, whiteInput;
    cout << "请输入黑棋坐标,格式如 0 5 8 9 9 10(用空格分隔): ";
    getline(cin, blackInput);
    cout << "请输入白棋坐标,格式如 5 0 9 9 9 8(用空格分隔): ";
    getline(cin, whiteInput);
    vector<pair<int, int>> black_positions = parseCoordinates(blackInput);
    vector<pair<int, int>> white_positions = parseCoordinates(whiteInput);
    int total_black_liberties = countSharedLiberties(black_positions);
    int total_white_liberties = countSharedLiberties(white_positions);
    cout << total_black_liberties << " " << total_white_liberties << endl; // 输出黑棋和白棋的气数

    system("pause");

    return 0;
}
相关推荐
hanhahai16 分钟前
指针与函数(函数指针与指针函数)
算法
码匠许师傅39 分钟前
【C++ 面试真题】聊聊 C++ 的序列容器
java·c++·面试
ValhallaCoder41 分钟前
Leetcode-hot100(2026.08.17)
python·算法·leetcode
C++ 老炮儿的技术栈1 小时前
Qt5.9.1 Windows 完整开发环境搭建流程
开发语言·c++·windows·qt·编辑器·代码化
泡沫冰@1 小时前
GO 语言基础
开发语言·算法·golang
键盘会跳舞2 小时前
C++:std::tuple 源码级深度拆解——变参模板、SFINAE与模板元编程核心技巧
开发语言·c++·sfinae·变参模板
bkspiderx2 小时前
从零开始:VS Code搭建C/C++开发环境全指南(Windows/macOS/Linux)
c语言·c++·windows·vs code·c/c++开发环境
东华万里2 小时前
第40篇C++核心基础与工程实践:从底层逻辑到避坑指南
开发语言·c++·面试·大学生专区
luj_17682 小时前
元设计的诱惑与现实
c语言·开发语言·c++·经验分享·算法
小星星闪亮登场2 小时前
ST表--倍增思想
开发语言·数据结构·c++·算法·思维