洛谷P10361 [PA 2024] Łamigłówka 3

给出一种朴素(暴力)做法

题面分析

给出的一个 \(n \times m\) 的目标网格图。每次操作能使一行或一列变为一种颜色,需要你构造一种在 \(n + m\) 次操作之内,将空图变成目标图的方案。

发现:每次操作后必有至少一行或一列为同一种颜色,相反地,我们也能从目标图每次找只有一种颜色的一行或一列来反推步骤。

关于具体实现

具体地,每次找到只有一种颜色的一行或一列抹除,抹除后这些格子的颜色可能为所有颜色,反着记录答案。

这个东西的时间复杂度明显是不对的,但是我们有一个优化方案:

  • 当所有行或者所有列都被抹除过显然已经还原成空图。

但时间复杂度仍然不对粗略估计有 \(O(n^3)\)

但是由于我们每次遍历时可以改变多个行和列,实际耗时远不及理论复杂度。

到这里测试下来只有一个点过不了。

再加上本题的大量输入输出,进行输入输出优化后可以过最后一个点。

Code

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

int rd()//快读

const int N = 2005;
int n,m,cnt;
int mp[N][N];

struct node
{
    char a,c;
    int b;
}a[N + N];
bool vis[N + N];

int num1,num2;

signed main()
{
    n = rd(),m = rd();
    for(int i = 1;i <= n;i++)
    {
        for(int j = 1;j <= m;j++)
        {
            char c = getchar();
            mp[i][j] = c - 'A';
        }
        getchar();
    }
    for(int i = 1;i <= n + m;i++)
    {
        for(int j = 1;j <= n;j++)
        {
            if(vis[j]) continue;
            bool f = 1;
            int x = -1;
            for(int k = 1;k <= m;k++) if(mp[j][k] != -1)
            {
                x = mp[j][k];
                break;
            }
            for(int k = 1;k <= m;k++) if(mp[j][k] != x && mp[j][k] != -1)
            {
                f = 0;
                break;
            }
            if(f)
            {
                num1++;
                vis[j] = 1;
                int c = -1;
                for(int k = 1;k <= m;k++) if(mp[j][k] != -1) c = mp[j][k],mp[j][k] = -1;
                if(c == -1) continue;
                a[++cnt].a = 'R';
                a[cnt].b = j;
                a[cnt].c = (char)(c + 'A');
            }
        }
        for(int j = 1;j <= m;j++)
        {
            if(vis[j + n]) continue;
            bool f = 1;
            int x = -1;
            for(int k = 1;k <= n;k++) if(mp[k][j] != -1)
            {
                x = mp[k][j];
                break;
            }
            for(int k = 1;k <= n;k++) if(mp[k][j] != x && mp[k][j] != -1)
            {
                f = 0;
                break;
            }
            if(f)
            {
                num2++;
                vis[j + n] = 1;
                int c = -1;
                for(int k = 1;k <= n;k++) if(mp[k][j] != -1) c = mp[k][j],mp[k][j] = -1;
                if(c == -1) continue;
                a[++cnt].a = 'K';
                a[cnt].b = j;
                a[cnt].c = (char)(c + 'A');
            }
        }
        if(num1 == n || num2 == m) break;
    }
    cout << cnt << '\n';
    for(int i = cnt;i >= 1;i--) cout << a[i].a << ' ' << a[i].b << ' ' << a[i].c << '\n';
    return 0;
}
posted @ 2025-07-10 17:51  IC0CI  阅读(5)  评论(0)    收藏  举报