在特定限制下让人们就座的方式数量

时间:2018-11-08 06:33:21

标签: algorithm dynamic-programming

我正在努力解决这个问题,因此,如果有人可以提供帮助,我们将不胜感激。问题是这样的:

计算k人在2 x n矩阵中的坐姿数量(n和k是通过标准输入从用户获得的)。矩阵也由用户提供,可以包含以下字符:“。” -人们可以坐在这里,“#”-人们不能坐在这里。

矩阵中的人不能相邻(也就是说,如果一个人位于(行,列),另一个人不能坐在(行1,列)或(行,列1) -请注意,他们可以坐在(第1行,第1列)上。

例如,如果n = 3,则k = 2并给出以下矩阵:

..#
...

答案是5。在矩阵中容纳2个人的所有可能方法是(u表示一个人坐在该字段上):

u.#   .u#   ..#   u.#   .u#
.u.   u..   u.u   ..u   ..u

1 个答案:

答案 0 :(得分:0)

让我们从左到右浏览2 x N矩阵。在每一列上,我们只能有3个状态:

  1. 用户处于最高位置
  2. 用户处于最低位置
  3. 没有用户

因此,在每个步骤中,我们都可以从先前的状态中移出,我们需要为每种状态和每个用户数保留多种方式:

  • 状态Top可以移至状态:BottomNone
  • 状态Bottom可以移至状态:TopNone
  • 状态None可以移至状态:TopBottomNone

答案是K个用户的所有状态的总和。

示例代码:

#include <iostream>
#include <map>
#include <string>
using namespace std;

enum State: int
{
    Top,    // u
            // -

    Bottom, // -
            // u

    None,   // -
            // -
};

int main()
{
    int N, K; cin >> N >> K;
    string S[2]; cin >> S[0] >> S[1];

    map<State, map<int, int>> prev = { { None, {{0,1}} } };
    for (int i = 0; i < N; ++i) {
        map<State, map<int, int>> cur;

        if (S[0][i] == '.') {
            for (auto& w : prev[None])   cur[Top][w.first + 1] += w.second;
            for (auto& w : prev[Bottom]) cur[Top][w.first + 1] += w.second;
        }
        if (S[1][i] == '.') {
            for (auto& w : prev[None]) cur[Bottom][w.first + 1] += w.second;
            for (auto& w : prev[Top])  cur[Bottom][w.first + 1] += w.second;
        }
        for (auto& w : prev[None])   cur[None][w.first] += w.second;
        for (auto& w : prev[Top])    cur[None][w.first] += w.second;
        for (auto& w : prev[Bottom]) cur[None][w.first] += w.second;

        swap(cur, prev);
    }

    cout << (prev[Top][K] + prev[Bottom][K] + prev[None][K]) << endl;
    return 0;
}