window.cnblogsConfig = {//可以放多张照片,应该是在每一个博文上面的图片,如果是多张的话,那么就随机换的。 homeTopImg: [ "https://i.loli.net/2019/08/02/5d440029af8e994539.png" ], }

AT_abc337_d 的题解

AT_abc337_d 的题解

题目大意

给你一个 \(H \times W(H \times W \leq 2 \times 10^5)\) 的矩阵,矩阵由 ox. 构成。存在一种操作:将一个 . 变成 o。问在一段连续的区间内,需要进行多少次操作才可以将同一行或同一列中的连续 \(k\) 个数都变为 o,若无法完成,输出 -1

思考过程

看到了可爱的 \(H \times W \leq 2 \times 10^5\),就知道这里必须使用复杂度为 \(O(HW)\) 的算法了。

考虑枚举每一列和每一行中的 \(k\) 个点是否能满足要求,并更新 ans,由于是连续 \(k\) 个点,我们需要使用一个类似队列的东西来维护,维护当前的列或者行中的连续 \(k\) 个点中有多少个 . 和多少个 x,有多少个 . 就是当前的最优答案,如果当前 \(k\) 个字符中有 x,就证明当前 \(k\) 个字符不符合题意。

Code

代码中也有详细解释,但不要直接复制。

#include <bits/stdc++.h>
using namespace std;

int n, m, k;
int ans = 0x3f3f3f3f;
int sum, flag;
string str;
vector<string>s; //直接用char的话会爆空间

int main()
{
    cin >> n >> m >> k;
    for (int i = 0; i < n; i++)
    {
        cin >> str;
        s.push_back(str);
    }
    for (int i = 0; i < n; i++)  //枚举每一行
    {
        sum = 0, flag = 0;    //sum记录该串中有多少个".",flag记录该串中有多少个"x"
        for (int j = 0; j < m; j++)
        {
            sum += (s[i][j] == '.'), flag += (s[i][j] == 'x');
            if (j >= k)    //确保此时比连续的k个多
                sum -= (s[i][j - k] == '.'), flag -= (s[i][j - k] == 'x');
            if (j + 1 >= k && flag == 0) //是连续的k个并且没有"x"
                ans = min(ans, sum);
        }
    }
    for (int i = 0; i < m; i++)  //枚举每一列
    {
        sum = 0, flag = 0;
        for (int j = 0; j < n; j++)
        {
            sum += (s[j][i] == '.'), flag += (s[j][i] == 'x');
            if (j >= k)
                sum -= (s[j - k][i] == '.'), flag -= (s[j - k][i] == 'x');
            if (j + 1 >= k && flag == 0)
                ans = min(ans, sum);
        }
    }
    if (ans == 0x3f3f3f3f)
        printf("-1");
    else
        printf("%d", ans);
    return 0;
}
posted @ 2024-01-21 16:53  mgcjade  阅读(38)  评论(0)    收藏  举报