Codeforces Round #607 (Div. 2) G. Beingawesomeism

题目大意

给出一个 r × c r\times c r×c的矩阵,
每次可以利用图中的一个 1 × d 1\times d 1×d或者 d × 1 d\times 1 d×1的子矩阵,并用其向一个方向(上下左右)移动,并用这个子矩阵的值来覆盖其的经过的地方。
问最少需要多少次才能让整个矩阵相同。

时间限制

2s

数据范围

r , c ≤ 60 r,c\le60 r,c≤60

题解

不难发现最多只需要 4 4 4,具体如下:
1.选定一个格子 ( x 0 , y 0 ) \pod{x_0,y_0} (x0​,y0​),并用其向左覆盖,直到左边界。
2.继续用格子 ( x 0 , y 0 ) \pod{x_0,y_0} (x0​,y0​)向右覆盖,直到右边界。
3.现在已经得到了一行完全相同的,用这一行向上覆盖,直到上边界。
4.继续用这行向下覆盖,直到下边界。

如何减少所需要的步数呢?
假设选取的格子 ( x 0 , y 0 ) \pod{x_0,y_0} (x0​,y0​)在边界上,那么显然它可以节省一次。

假设选取的格子 ( x 0 , y 0 ) \pod{x_0,y_0} (x0​,y0​)恰好在角落,或者已经有现成的一行(列)相同的话,那么就仅仅需要两次。

如果现成相同的行(列)恰好在边界上,那么仅仅需要一次。

这题没有什么难度,但分类讨论需要注意细节

Code

//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <queue>
#define G getchar
#define ll long long
using namespace std;

ll read()
{
    char ch;
    for(ch = G();(ch < '0' || ch > '9') && ch != '-';ch = G());
    ll n = 0 , w;
    if (ch == '-')
    {
        w = -1;
        ch = G();
    } else w = 1;
    for(;'0' <= ch && ch <= '9';ch = G())n = (n<<1)+(n<<3)+ch-48;
    return n * w;
}

const int N = 63;
bool bz[N][N];
int flag;
int n , m , s1[N] , s2[N];
char ch;

bool pd1()
{
    return (s1[1] == m) || (s1[n] == m) || (s2[1] == n) || (s2[m] == n);
}

bool pd3()
{

    return s1[1] || s1[n] || s2[1] || s2[m];
}

bool pd2()
{
    for (int i = 2 ; i < n; i++)
        if (s1[i] == m) return 1;

    for (int i = 2 ; i < m ; i++)
        if (s2[i] == n) return 1;

    return bz[1][1] || bz[1][m] || bz[n][1] || bz[n][m];
}

int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);

    for (int t = read() ; t ; t--)
    {
        n = read();
        m = read();
        flag = 0;
        memset(s1 , 0 , sizeof(s1));
        memset(s2 , 0 , sizeof(s2));
        for (int i = 1 ; i <= n ; i++)
        {
            for (ch = G() ; ch != 'A' && ch !='P' ; ch = G());
            for (int j = 1 ; j <= m ; j++)
            {
                if (ch == 'A')
                {
                    bz[i][j] = 1;
                    flag++;
                    s1[i]++;
                    s2[j]++;
                } else bz[i][j] = 0;
                ch = G();
            }
        }

        if (flag == 0)
        {
            puts("MORTAL");
            continue;
        }

        if (flag == n * m)
        {
            puts("0");
            continue;
        }

        if (pd1())
        {
            puts("1");
            continue;
        }

        if (pd2())
        {
            puts("2");
            continue;
        }

        if(pd3())
        {
            puts("3");
            continue;
        }

        puts("4");

    }
    
    return 0;
}
上一篇:支持复制粘贴word图片的文本编辑器


下一篇:前端图片上传的方式