【问题标题】:How many squares can M bishops cannot go in an N*N chess board?在 N*N 棋盘中,M 个象不能走多少个方格?
【发布时间】:2020-02-22 09:25:41
【问题描述】:

我目前正在开发一个程序,该程序计算 M 数量的主教在 N*N 大小的国际象棋网格上的移动。我有一个程序可以只为一位主教找到无法访问的方格。有人可以帮我解决这个问题吗?

#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int ways(int r,int c,int n)
{
    int TL,TR,BL,BR;
    TL = min(r,c) - 1;
    TR = min(r,(n+1)-c) - 1;
    BL = n - max(r,(n+1)-c);
    BR = n - max(r,c);
    return (TL+TR+BL+BR);
}

int main()
{
    int r,c,n;
    cin >> r >> c >> n;
    cout << n*n - ways(r,c,n);
    return 0;
}

如果主教的行列都是4,网格大小是8*8,那么那个主教有51个方格是它不能访问的。但我不知道我应该如何处理这个问题。

【问题讨论】:

  • 请对您提到的代码进行minimal reproducible example。然后解释它可以做什么并描述它应该做什么的区别。理想情况下还显示代码输出并给出您需要的输出示例。如果可能,请描述您认为可能有用的机制、结构或算法的任何想法。您展示的自己的研究和工作越多,您获得的帮助就越多。
  • @Yunnosch 好的,我添加了程序,接下来我该怎么做?

标签: c++ chess


【解决方案1】:

有几种方法可以完成这项任务,但我会给你一个简单的算法。

主教不能访问的方格数=

方格数-主教可以访问的方格数

由于计算方格总数 (n * n) 很容易,所以问题归结为计算这些主教从其给定位置可以访问的方格总数。

在您的代码中,您不会读取主教的数量及其初始坐标。这应该是第一步。

由于您使用 C++ 工作,您可以使用 std::setstd::pair 来简化您的任务。集合用于存储唯一元素,因此您可以使用它来存储主教可以访问的位置并避免重复。一对可用于将位置存储为坐标(i, j)

遍历每个主教并计算他们可以访问的方格并将其添加到集合中。最后,您得到了主教可以覆盖的方格总数,作为该集合的大小。

然后使用上面的公式得到你想要的结果。

以下是该方法的实现:

#include <iostream>
#include <set>
#include <utility>

using namespace std;

int main()
{
    int n; // Size of the chess board
    int m; // Number of bishops
    int x, y; // Initial location of a bishop
    int i, j; // Coordinates for iteration

    // Read the limits
    cin >> n >> m;
    if (n < 0) n = 0;

    // Read the location of the bishops
    set<pair<int, int>> bishops;
    for (i = 0; i < m; ++i)
    {
        cin >> x >> y;
        if (x >= 0 && x < n && y >= 0 && y < n)
            bishops.insert({x, y});
    }

    // This is the key
    set<pair<int, int>> visitableLocations;

    // Calculate the squares that could be visited by all the bishops
    for (const auto& bishop : bishops)
    {
        x = bishop.first;
        y = bishop.second;
        /*
        You don't need this after the edit made to your post
        Because you don't consider its initial square as visitable
        // Add the original location of the bishop
        if (x >= 0 && x < n && y >= 0 && y < n)
            visitableLocations.insert({x, y});
        */

        // Check all the diagonal directions
        // Within the boundaries of the board
        // No other bishop should block the way

        // auto debug = [&](){cout << i << ' ' << j << '\n';};

        // north-east
        i = x; j = y;
        while (++i < n && ++j < n)
            if (bishops.find({i, j}) == bishops.end())
                visitableLocations.insert({i, j});//debug();}

        // north-west
        i = x; j = y;
        while (--i >= 0 && ++j < n)
            if (bishops.find({i, j}) == bishops.end())
                visitableLocations.insert({i, j});//debug();}

        // south-east
        i = x; j = y;
        while (++i < n && --j >= 0)
            if (bishops.find({i, j}) == bishops.end())
                visitableLocations.insert({i, j});//debug();}

        // south-west
        i = x; j = y;
        while (--i >= 0 && --j >=0)
            if (bishops.find({i, j}) == bishops.end())
                visitableLocations.insert({i, j});//debug();}
    }

    // Now get the final answer
    int ans = (n * n) - visitableLocations.size();
    cout << ans;

    return 0;
}

【讨论】:

  • @ICYCounter-StrikeandLeague 不客气。如果您在实施该算法时遇到困难,请随时提问,我会相应地编辑我的答案。如果需要,您还可以对其进行优化。
  • 还是想不通。唯一的问题是配对功能。我从来没有用过它。我了解算法,但不了解配对函数。
  • 好吧@ICYCounter-StrikeandLeague 给我几分钟,我会给你一些代码。顺便说一句,std::pair 是一个 容器 而不是函数。它属于 STL。你可能需要一些时间来学习 STL,它真的很棒而且很有用。
  • @ICYCounter-StrikeandLeague 我尝试使用std::unordered_set 来加速程序,但不幸的是标准库没有为std::pair 提供哈希函数。我在后面迷路了大声笑我很快就会给你的程序。完成了,只剩下测试了。
  • 我已经很久没有使用STL了,我遇到了一些逻辑错误。你能等一下@ICYCounter-StrikeandLeague 吗?
猜你喜欢
  • 1970-01-01
  • 2021-12-15
  • 2016-03-11
  • 1970-01-01
  • 2015-07-02
  • 2017-05-27
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
相关资源
最近更新 更多