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

内存小炸裂,但是成功了

相关推荐
_安晓7 分钟前
数据结构 -- 树形查找(三)红黑树
数据结构
じ☆ve 清风°15 分钟前
滑动窗口算法详解与C++实现
开发语言·c++·算法
苕皮蓝牙土豆20 分钟前
C++ map & multimap 容器:赋值、排序、大小与删除操作
开发语言·c++
tmacfrank21 分钟前
Android 性能优化入门(一)—— 数据结构优化
android·数据结构·性能优化
东莞呵呵40 分钟前
吴恩达机器学习(1)——机器学习算法分类
算法·机器学习·分类
虾球xz43 分钟前
游戏引擎学习第293天:移动Familiars
c++·学习·游戏引擎
lichuangcsdn1 小时前
【springcloud学习(dalston.sr1)】Eureka服务端集群的搭建(含源代码)(二)
学习·spring cloud·eureka
名誉寒冰1 小时前
RPC框架源码分析学习(二)
qt·学习·rpc
孙同学_1 小时前
【C++】map和set的使用
开发语言·c++
wjm0410061 小时前
C++中的容器
开发语言·c++