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

内存小炸裂,但是成功了

相关推荐
爱上妖精的尾巴4 小时前
3-5 WPS JS宏 工作表的移动与复制学习笔记
javascript·笔记·学习·wps·js宏·jsa
屁股割了还要学6 小时前
【计算机网络入门】初学计算机网络(五)
学习·计算机网络·考研·青少年编程
屁股割了还要学6 小时前
【计算机网络入门】初学计算机网络(七)
网络·学习·计算机网络·考研·青少年编程
萧毅寒7 小时前
leetcode第40题组合总和Ⅱ
算法·leetcode·职场和发展
_extraordinary_7 小时前
动态规划刷题
算法·动态规划
萌の鱼7 小时前
leetcode 48. 旋转图像
数据结构·c++·算法·leetcode
数据攻城小狮子7 小时前
深入剖析 OpenCV:全面掌握基础操作、图像处理算法与特征匹配
图像处理·python·opencv·算法·计算机视觉
xinghuitunan7 小时前
奖学金(acwing)c++
算法
机器学习之心8 小时前
分类预测 | Matlab实现CPO-SVM冠豪猪算法优化支持向量机多特征分类预测
算法·matlab·分类·cpo-svm
win水8 小时前
数据结构(初阶)(七)----树和二叉树(堆,堆排序)
数据结构