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

内存小炸裂,但是成功了

相关推荐
Scc_hy11 分钟前
强化学习_Paper_1988_Learning to predict by the methods of temporal differences
人工智能·深度学习·算法
巷北夜未央12 分钟前
Python每日一题(14)
开发语言·python·算法
javaisC14 分钟前
c语言数据结构--------拓扑排序和逆拓扑排序(Kahn算法和DFS算法实现)
c语言·算法·深度优先
爱爬山的老虎15 分钟前
【面试经典150题】LeetCode121·买卖股票最佳时机
数据结构·算法·leetcode·面试·职场和发展
SWHL15 分钟前
rapidocr 2.x系列正式发布
算法
梅子酱~16 分钟前
Vue 学习随笔系列二十二 —— 表格高度自适应
javascript·vue.js·学习
s_little_monster20 分钟前
【Linux】进程信号的捕捉处理
linux·运维·服务器·经验分享·笔记·学习·学习方法
阳光_你好30 分钟前
请详细说明opencv/c++对图片缩放
c++·opencv·计算机视觉
杰克逊的黑豹37 分钟前
不再迷茫:Rust, Zig, Go 和 C
c++·rust·go
雾月5540 分钟前
LeetCode 914 卡牌分组
java·开发语言·算法·leetcode·职场和发展