1068 万绿丛中一点红(map, 简化处理周围数据, vector::resize(), sizeof())

解析一道寻找图像中独一无二颜色像素点的编程题,分享代码实现与关键知识点,包括vector::resize()、map容器使用及周围数据简化处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于计算机而言,颜色不过是像素点对应的一个 24 位的数值。现给定一幅分辨率为 M×N 的画,要求你找出万绿丛中的一点红,即有独一无二颜色的那个像素点,并且该点的颜色与其周围 8 个相邻像素的颜色差充分大。

输入格式:

输入第一行给出三个正整数,分别是 M 和 N(≤ 1000),即图像的分辨率;以及 TOL,是所求像素点与相邻点的颜色差阈值,色差超过 TOL 的点才被考虑。随后 N 行,每行给出 M 个像素的颜色值,范围在 [0,2​24​​) 内。所有同行数字间用空格或 TAB 分开。

输出格式:

在一行中按照 (x, y): color 的格式输出所求像素点的位置以及颜色值,其中位置 x 和 y 分别是该像素在图像矩阵中的列、行编号(从 1 开始编号)。如果这样的点不唯一,则输出 Not Unique;如果这样的点不存在,则输出 Not Exist

输入样例 1:

8 6 200
0 	 0 	  0 	   0	    0 	     0 	      0        0
65280 	 65280    65280    16711479 65280    65280    65280    65280
16711479 65280    65280    65280    16711680 65280    65280    65280
65280 	 65280    65280    65280    65280    65280    165280   165280
65280 	 65280 	  16777015 65280    65280    165280   65480    165280
16777215 16777215 16777215 16777215 16777215 16777215 16777215 16777215

输出样例 1:

(5, 3): 16711680

输入样例 2:

4 5 2
0 0 0 0
0 0 3 0
0 0 0 0
0 5 0 0
0 0 0 0

输出样例 2:

Not Unique

输入样例 3:

3 3 5
1 2 3
3 4 5
5 6 7

输出样例 3:

Not Exist

分析:

       一开始对于题干中的“独一无二”理解有错,我以为是颜色差充分大中独一无二的点,而实际上指的是所有点中独一无二的。因此我在原来代码的基础上进行修改,显得十分麻烦,就不贴上来了。这里贴上小姐姐的代码吧:

#include<iostream>
#include<vector>
#include<map>

using namespace std;

int m, n, tol;
vector<vector<int>> v;
int dir[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}};
bool Judge(int i, int j){
	for(int k = 0; k < 8; k++){
		int tx = i + dir[k][0];
		int ty = j + dir[k][1];
		if (tx >= 0 && tx < n && ty >= 0 && ty < m && v[i][j] - v[tx][ty] >= 0 - tol && v[i][j] - v[tx][ty] <= tol) return false;
	}
	return true;
}

int main(){
	int cnt = 0, x = 0, y = 0;
	scanf("%d%d%d", &m, &n, &tol);
	v.resize(n, vector<int>(m));
	map<int, int> mapp;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			scanf("%d", &v[i][j]);
			mapp[v[i][j]]++;
		}
	}
	for(int i = 0; i < n; i++){
		for(int j = 0; j < m; j++){
			if(mapp[v[i][j]] == 1 && Judge(i, j) == true){
				cnt++;
				x = i + 1;
				y = j + 1;
			}
		}
	}
	if(cnt == 1)
        printf("(%d, %d): %d", y, x, v[x-1][y-1]);
    else if(cnt == 0)
        printf("Not Exist");
    else
        printf("Not Unique");
}

       题目很简单,就不多解释什么了。这里记录一下学到的知识点吧:

1.sizeof():

       这是在我的代码中遇到的问题,在使用memset时,我看到有人是这样用的:

int *array = new int [n];
memset(array, 0, sizeof(array));

       一开始我没细想它是不是对的,但是写代码的过程中发现这是错误的用法。需要注意的是array在这里是指针,所以sizeof(array)的结果当然是指针所占空间的大小。应当写为:

int *array = new int [n];
memset(array, 0, sizeof(int) * n);

2.vector::resize():

       首先要理解一下小姐姐写的这行代码:

v.resize(n, vector<int>(m));

       v的类型是<vector<vector<int>>,第一个参数n,是设置v有n个vector<int>的元素,vector<int>(m)表示构造一个无名且含有m个0(默认初始化为0)的vector<int>对象。

       如果你搜索一下vector::resize()与发现很多博文会写它与vector::reserve()的区别:其实就是size与capacity的区别,resize()改变size,reserve()改变capacity。那么size和capacity的区别是什么呢?有人打了这么一个比喻,一辆公交车上假如可以容纳40个座位,而实际上只安装了35个。那么35就是size,40就是capacity。

       resize()可以改变容器的大小,并且创建对象。

       当容器内的元素超过了容器的容量(capacity),它是这样扩容的:重新找一块儿更大的内存,然后把原容器内的元素拷贝到新容器内,然后释放原容器的空间。如果事先分配好了空间,就不需要进行多次扩容的操作了。

       reserve(size_type n)用来预分配存储区大小,但没有进行初始化。参数n是推荐预分配内存的大小,实际分配的可能等于或大于这个值。即n大于capacity的值,就会重新分配内存,capacity的值会大于或者等于n; 如果capacity >= n则无变化。这样,当size超过默认分配的capacity时,避免了内存重新分配开销。注意:reserve()分配出来的空间,只是表示vector可以利用这部分内存,但不能有效访问。

       可参考如下代码:

#include<iostream>
#include<vector>

using namespace std;

int main(){
	vector<int> a;
	cout << a.capacity() << endl;
	a.reserve(100);
	a.resize(50);
	cout<< a.size() << "  " << a.capacity() << endl;
	a.resize(150);
	cout<< a.size() << "  " << a.capacity() << endl;
	a.reserve(50);
	cout<< a.size() << "  " << a.capacity() << endl;
	a.resize(50);
	cout<< a.size() << "  " << a.capacity() << endl;
}

3.简化处理周围数据:

       我原来的代码在这一块儿就写的很冗杂,之前在写八皇后,五子棋,生命游戏等问题时也遇到了这样的麻烦。看了小姐姐巧妙的处理方式不禁赞叹,在上面的代码中就有,学会就好了。

4.map:

       map是STL的容器,提供一对一的hash。

       ①map添加数据

        map<int ,string> maplive;  
       1.pair<int,string> value(1,"a");maplive.insert(value);

       等价于maplive.insert(pair<int,string>(1,"a"));

       2. maplive.insert(map<int,string>::value_type(1,"a"));

       3. maplive[1]="a";// 最常用的方式

       三、map的基本操作函数:

  begin()          返回指向map头部的迭代器
  clear()         删除所有元素
       count()          返回指定元素出现的次数
       empty()          如果map为空则返回true
       end()            返回指向map末尾的迭代器
       equal_range()    返回特殊条目的迭代器对
       erase()          删除一个元素
       find()           查找一个元素
       get_allocator()  返回map的配置器
       insert()         插入元素
       key_comp()       返回比较元素key的函数
       lower_bound()    返回键值>=给定元素的第一个位置
       max_size()       返回可以容纳的最大元素个数
       rbegin()         返回一个指向map尾部的逆向迭代器
       rend()           返回一个指向map头部的逆向迭代器
       size()           返回map中元素的个数
       swap()            交换两个map
       upper_bound()     返回键值>给定元素的第一个位置
       value_comp()      返回比较元素value的函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值