专栏文章

题解:CF2090B Pushing Balls

CF2090B题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miptzyv7
此快照首次捕获于
2025/12/03 17:55
3 个月前
此快照最后确认于
2025/12/03 17:55
3 个月前
查看原文

简要题意

对于一个 n×mn\times m 的网格,进行了若干次操作,每次往网格的最上端或者最左端推入一个球,如果最上端或者最左端已经有球,那么之前的球会向下或向右(即被推至里部)以空出位置给新推入的球。
现给出网格的最终状态,判断其是否合法,即是否可以通过题目所述的方法达到此状态。

思路

对于每个有球的格子,球只可能从行首或列首推入,并由其他球推到该位置。因此其上所有的格子或其左所有的格子必有其一是被球填满的,以表明球是从此方向推入而来的。
因此,对于每个球,我们检查每个球上方所有的格子是否都为 11,或左边所有的格子是否都为 11,满足其一即可。如果二者皆不满足,证明此状态是不合法的。
为降低时间复杂度,可以先预处理出每个球的上方格子或左边格子是否皆为 11,并存储在 r_prec_pre 中。
CPP
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n, m;
        cin >> n >> m;
        vector<string> a(n);
        for (int i = 0; i < n; ++i) cin >> a[i];
        vector<vector<bool>> c_pre(m, vector<bool>(n + 1, false));
        vector<vector<bool>> r_pre(n, vector<bool>(m + 1, false));
        for (int i = 0; i < n; ++i)
        {
            r_pre[i][0] = true;
            for (int j = 1; j <= m; ++j) r_pre[i][j] = r_pre[i][j - 1] && (a[i][j - 1] == '1');
        }
        for (int j = 0; j < m; ++j)
        {
            c_pre[j][0] = true;
            for (int i = 1; i <= n; ++i) c_pre[j][i] = c_pre[j][i - 1] && (a[i - 1][j] == '1');
        }
        bool flag = true;
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < m; ++j)
            {
                if (a[i][j] == '1')
                {
                    bool R = r_pre[i][j];
                    bool C = c_pre[j][i];
                    if (!R && !C)
                    {
                        flag = false;
                        goto end;
                    }
                }
            }
        }
    end:
        cout << (flag ? "YES" : "NO") << '\n';
    }
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...