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;
}

内存小炸裂,但是成功了

相关推荐
一只旭宝17 小时前
回调函数(Callback)
linux·服务器·算法
秋名RG17 小时前
算法的划分
算法
牵猫散步的鱼儿17 小时前
C++ 内存分区
c++
Tisfy17 小时前
LeetCode 3619.总价值可以被 K 整除的岛屿数目:广度优先搜索BFS
算法·leetcode·bfs·宽度优先
地平线开发者17 小时前
【大模型】EAGLE 与 EAGLE-3:用“特征预测“加速投机解码
算法
choumin17 小时前
C++ 标准容器为什么不能存引用
c++·容器·引用类型
Li_RuiQi17 小时前
DAgger与交互式模仿学习_ACT学习笔记
笔记·学习
谙弆悕博士17 小时前
用 C 写了个 Windows 聊天室,踩了几个多线程和控制台的坑
c语言·开发语言·c++·windows·网络编程·聊天室
Canmag 兴隆磁性17 小时前
回复磁导率 μ_R:永磁体在动态磁路中的关键参数
开发语言·学习·r语言·永磁材料·充磁·磁导率
lengxuenong18 小时前
区间覆盖问题 · 简明学习手册1
java·学习·算法