Educational Codeforces Round 174 (Rated for Div. 2)

Problem - B - Codeforces

之前没思路,我看了看答案。

思路不就来了:

简而言之,BFS那样遍历周围(上下左右均一次),如果有同色,就把这部分相邻的隔开,可以得到两块陌生人集合,就能解决,

每种颜色,最少要1次变换,最多要两次变换。

在写之前,我再优化一下:在录入当前颜色的时候,查找当前位置左方和上方的颜色,看看是否同色。

就是一这部分相邻的隔开,可以得到两块陌生人集合,就能解决

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
vector<vector<int>>arr;
vector<int>ok;
int m, n;
int reach;


void check(int a, int b)
{
	int now = arr[a][b];
	int up[2] = { -1,0 };
	int right[2] = { 0,-1};
	for (int i = 0; i < 2; i++)
	{
		if (a + up[i] < 0 || a + up[i] >= m || b + right[i] < 0 || b + right[i] >= n)
		{
			continue;
		}
		if (arr[a + up[i]][b + right[i]] == now)
		{
			if (ok[now] != -1)
			{
				reach++;
				ok[now] = -1;
			}
		}
	}
}



int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		cin >> m >> n;
		arr=vector<vector<int>>(m, vector<int>(n));
		ok= vector<int>(5000);
		int sum = 0;
		reach = 0;

		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
			{
				cin >> arr[i][j];
					if (ok[arr[i][j]]>0)
					{
						check(i, j);
					}
					if (ok[arr[i][j]] == 0)
					{
						ok[arr[i][j]]++;
						sum++;
					}
					//等于-1什么也不做
				
			}		

		if (reach > 0)
		{
			cout << sum - reach + (reach - 1) * 2<<endl;
		}
		else
		{
			
			cout << sum-1 << endl;
		}

	}
}

超时,为什么呢?因为每次都会开一个5000大小的数组用来记住颜色,这样不行

试试键值对

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

vector<vector<int>> arr; // 存储表格数据
unordered_map<int, int> ok; // 使用 unordered_map 代替数组
int m, n; // 表格的行数和列数
int reach; // 记录满足某种条件的颜色数量

// 检查函数:检查当前单元格的颜色是否与上方或左方的单元格颜色相同
void check(int a, int b) {
    int now = arr[a][b]; // 当前单元格的颜色
    int up[2] = { -1, 0 }; // 上方单元格的偏移量
    int right[2] = { 0, -1 }; // 左方单元格的偏移量

    // 检查上方和左方的单元格
    for (int i = 0; i < 2; i++) {
        // 检查边界条件,避免越界
        if (a + up[i] < 0 || a + up[i] >= m || b + right[i] < 0 || b + right[i] >= n) {
            continue; // 如果越界,跳过
        }

        // 如果上方或左方的单元格颜色与当前单元格相同
        if (arr[a + up[i]][b + right[i]] == now) {
            if (ok[now] != -1) { // 如果该颜色尚未被标记为冲突
                reach++; // 增加冲突计数
                ok[now] = -1; // 标记该颜色为冲突
            }
        }
    }
}

int main() {
    int t; // 测试用例的数量
    cin >> t; // 读取测试用例数量
    while (t--) { // 处理每个测试用例
        cin >> m >> n; // 读取表格的行数和列数
        arr = vector<vector<int>>(m, vector<int>(n)); // 初始化表格
        ok.clear(); // 清空键值对
        int sum = 0; // 记录颜色的总数
        reach = 0; // 重置冲突计数

        // 读取表格数据并处理
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                cin >> arr[i][j]; // 读取当前单元格的颜色
                if (ok[arr[i][j]] > 0) { // 如果该颜色已经出现过
                    check(i, j); // 检查是否与相邻单元格冲突
                }
                if (ok[arr[i][j]] == 0) { // 如果该颜色第一次出现
                    ok[arr[i][j]]++; // 标记该颜色存在
                    sum++; // 增加颜色总数
                }
                // 如果 ok[arr[i][j]] == -1,说明该颜色已经标记为冲突,无需处理
            }
        }

        // 输出结果
        if (reach > 0) { // 如果存在冲突
            cout << sum - reach + (reach - 1) * 2 << endl; // 计算结果
        } else { // 如果没有冲突
            cout << sum - 1 << endl; // 直接输出颜色总数减 1
        }
    }
    return 0;
}

内存小炸裂,但是成功了

相关推荐
纪元A梦4 分钟前
华为OD机试真题——绘图机器(2025A卷:100分)Java/python/JavaScript/C++/C/GO最佳实现
java·javascript·c++·python·华为od·go·华为od机试题
钢铁男儿6 分钟前
C# 深入理解类:面向对象编程的核心数据结构
开发语言·数据结构·c#
蓝莓味柯基11 分钟前
DevOps:概念与学习路径
运维·学习·devops
赏你个麻辣烫儿14 分钟前
机器学习学习笔记
笔记·学习
hy.z_77717 分钟前
【数据结构刷题】顺序表与ArrayList
数据结构
天哥-天行健18 分钟前
Trae+DeepSeek学习Python开发MVC框架程序笔记(一):1个程序实现MVC
学习·mvc
Felven34 分钟前
A. Everybody Likes Good Arrays!
数据结构·算法
huangyuchi.1 小时前
【C++11】Lambda表达式
开发语言·c++·笔记·c++11·lambda·lambda表达式·捕捉列表
什么半岛铁盒1 小时前
Linux线程与进程:探秘共享地址空间的并发实现与内
linux·c++
LVerrrr1 小时前
Missashe考研日记-day27
学习·考研