原题链接1068 万绿丛中一点红
这道题,其实我觉得题目可以描述的再精确一点。我一开始就有点困惑
原题要求:
要求你找出万绿丛中的一点红,即有独一无二颜色的那个像素点,并且该点的颜色与其周围 8 个相邻像素的颜色差充分大。
首先很明确的一点是,是要找出独一无二的那个颜色点。所以,可以使用unorderde_map < int,int > 在读入数据时就统计各个颜色的出现次数,这样在遍历时,首先判断当前颜色是否出现过大于一次,如果是,则当前颜色肯定不是答案,直接跳过当前颜色。
其次就是题目说的有点模糊的一点了,这里说是该点的颜色与其周围 8 个相邻像素的颜色差充分大,但是如果代码中,对于边缘以及角落处的数据,也即周围没有8个相邻数据的点跳过了,那么会出错。其实就是说,对于任何位置的点都要检查。而周围有几个数据点取决于该数据位置,如果是角落就是周围有3个数据,若是边界,则周围有5个数据。
再次,我一开始还困惑在,当前点处的颜色值,是要比周围的点的颜色值都要大,或者都要小吗?其实不是的,只用比较绝对值即可。
仔细检查样例一
可以发现第二行的16711479与周围的8个点的颜色差值的绝对值都要大于200,虽然其周围的8个点中,有7个小于它,有一个大于它,但是为什么不选这个点?因为在第三行,这个点又出现了,并且,在第三行的开头位置处,这个点符合比其周围的颜色值都要大200。
AC代码
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
int n,m,dif; //依次是行数,列数,差值
int data[1010][1010]; //用于存放颜色数据
int dy[] = {
-1,1,0,0,-1,-1,1,1};//控制上下
int dx[] = {
0,0,-1,1,-1,1,-1,1};//控制左右
unordered_map<int,int> vis; //用于标记颜色值出现次数
bool judge(int y,int x){
//用于判断是否是有效位置
return y >= 1 && y <= n && x >=1 && x <= m;
}
int main()
{
scanf("%d%d%d",&m,&n,&dif);
for(int y = 1;y <= n;y++){
//注意存放位置为从1开始
for(int x = 1;x <= m;x++){
scanf("%d",&data[y][x]);
vis[data[y][x]]++; //令颜色出现次数加一
}
}
int cnt = 0;
int ansx,ansy;
for(int y = 1;y <= n;y++){
for(int x = 1;x <= m;x++){
if(vis[data[y][x]] > 1) continue;//如果这个颜色出现多次,则跳过
bool tag = true;
for(int i = 0;i < 8;i++){
int newy = y + dy[i];
int newx = x + dx[i];
if(judge(newy,newx)){
//旁边位置有效
if(abs(data[y][x] - data[newy][newx]) <= dif){
tag = false;
break;
}
}
}
if(tag){
cnt++;
if(cnt > 1){
printf("Not Unique");
return 0;
}
ansx = x,ansy = y;
}
}
}
if(!cnt) printf("Not Exist");
else printf("(%d, %d): %d",ansx,ansy,data[ansy][ansx]);
return 0;
}