题目
很多修图软件提供了类似于魔法棒的功能,当你点选一个像素的时候,会同时帮你把附近相似颜色的像素摘取出来形成一个选区。其背后的简单逻辑是根据你选择的像素点向外扩充(上下左右),当相邻像素和被选中的像素存在相似的时候就选上,并继续向外扩充判断。
先拟定判断相似的条件为像素点的灰度值与被选的点差值在阈值以内(不包含阈值)的判断其为相似像素。
一个像素点的灰度值根据unit8_t类型来表示,以下面的二维数组为例子:
38 182 36 37 38 39
40 54 206 140 38 40
36 40 243 181 39 94
38 36 196 37 239 38
37 38 25 38 36 39
假设阈值为3,被选中的像素点坐标为4,1(标红数据,左上角为原点,从0开始,x方向指向右,y方向指向下),则被筛选出的区域合集(标绿部分及被选点本身)为(2,0),(3,0),(4,0),(4,1),(4,2),(5,0),(5,1)
现要求阈值,被选中的坐标和图像数据作为参数进行输入,输出被选择的选区的点坐标个数。
输入描述
第一行输入五个整数N,M,X,Y,T(N和M均大于0且小于等于1000),以空格隔开,N为该二维数组的行数,M为该二维数组的列数,X和Y为坐标(X>=0且X<N,Y>0且Y<M),T为阈值(T>=0且T<=255)
接下来N行,每行都有M格数字,为图像的数据,数值范围为[0,255]
输出描述
输出被选择的选区的点坐标个数
样例输入
6 6 2 3 3
37 37 39 41 13 205
37 41 41 203 39 243
37 41 40 131 40 41
91 41 39 198 41 9
189 41 39 40 40 38
37 124 38 167 41 41
样例输出
24
提示
若采用递归的解法需要考虑堆栈是否可能溢出
解析:
方法一:BFS
#include <iostream>
using namespace std;
#include <queue>
#include <vector>
class Solution {
public:
int findNumOfLink(vector<vector<int>>& grid, int x, int y, int T) {
int ans = 0;
int m = grid.size(), n = grid[0].size();
int d[4][2] = { {0,1}, {1,0}, {0,-1},{-1,0} };
queue<int> q;
vector<bool> visited(m * n, false);
q.push(x * n + y);
visited[x * n + y] = true;
while (!q.empty()) {
int sz = q.size();
for (int i = 0; i < sz; i++) {
int cur = q.front();
int curX = cur / n;
int curY = cur % n;
q.pop();
ans++;
for (int k = 0; k < 4; k++) {
int nextX = curX + d[k][0];
int nextY = curY + d[k][1];
if (nextX >= 0 && nextX < m && nextY >= 0 && nextY < n
&& !visited[nextX * n + nextY] && abs(grid[nextX][nextY] - grid[x][y]) < T) {
q.push(nextX * n + nextY);
visited[nextX * n + nextY] = true;
}
}
}
}
return ans;
}
};
int main() {
int N, M, X, Y, T;
cin >> N >> M >> X >> Y >> T;
vector<vector<int>> grid(N, vector<int>(M));
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> grid[i][j];
}
}
Solution solve;
int ans = solve.findNumOfLink(grid, Y, X, T);
cout << ans << endl;
return 0;
}
方法二:并查集
#include <iostream>
using namespace std;
#include <vector>
class UF {
public:
int count;
vector<int> parent;
vector<int> size;
UF(int n) {
count = n;
parent.resize(n);
size.resize(n);
for (int i = 0; i < n; i++) {
parent[i] = i;
size[i] = 1;
}
}
void Union(int p, int q) {
int rootP = find(p);
int rootQ = find(q);
if (rootP == rootQ) {
return;
}
if (size[rootP] < size[rootQ]) {
parent[rootP] = rootQ;
size[rootQ] += size[rootP];
}
else {
parent[rootQ] = rootP;
size[rootP] += size[rootQ];
}
count--;
}
bool connected(int p, int q) {
int rootP = find(p);
int rootQ = find(q);
return rootP == rootQ;
}
int find(int x) {
while (parent[x] != x) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
};
class Solution {
public:
int findNumOfLink(vector<vector<int>>& grid, int x, int y, int T) {
int ans = 0;
int m = grid.size(), n = grid[0].size();
int d[4][2] = { {0,1}, {1,0}, {0,-1},{-1,0} };
UF* uf = new UF(m * n);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (abs(grid[i][j] - grid[x][y]) >= T) {
continue;
}
for (int k = 0; k < 4; k++) {
int nextX = i + d[k][0];
int nextY = j + d[k][1];
if (nextX >= 0 && nextX < m && nextY >= 0 && nextY < n
&& abs(grid[nextX][nextY] - grid[x][y]) < T ) {
//cout << grid[nextX][nextY] << "--"<< grid[x][y] << endl;
uf->Union(i * n + j, nextX * n + nextY);
}
}
}
}
int p = uf->parent[x * n + y];
return uf->size[p];
}
};
int main() {
int N, M, X, Y, T;
cin >> N >> M >> X >> Y >> T;
vector<vector<int>> grid(N, vector<int>(M));
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> grid[i][j];
}
}
Solution solve;
int ans = solve.findNumOfLink(grid, Y, X, T);
cout << ans << endl;
return 0;
}
方法三:DFS
#include <iostream>
using namespace std;
#include <vector>
class Solution {
public:
int chooce = 0;
int ans = 0;
int findNumOfLink(vector<vector<int>>& grid, int x, int y, int T) {
this->chooce = grid[x][y];
vector<bool> visited(grid.size() * grid[0].size(), false);
dfs(grid, x, y, T, visited);
return ans;
}
void dfs(vector<vector<int>>& grid, int i, int j, int T, vector<bool> &visited) {
int m = grid.size(), n = grid[0].size();
if (i < 0 || i >= m || j < 0 || j >= n){
return;
}
if (visited[i * n + j] || abs(grid[i][j] - chooce) >= T) {
return;
}
ans++;
visited[i * n + j] = true;
dfs(grid, i + 1, j, T, visited);
dfs(grid, i - 1, j, T, visited);
dfs(grid, i, j + 1, T, visited);
dfs(grid, i, j - 1, T, visited);
}
};
int main() {
int N, M, X, Y, T;
cin >> N >> M >> X >> Y >> T;
vector<vector<int>> grid(N, vector<int>(M));
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> grid[i][j];
}
}
Solution solve;
int ans = solve.findNumOfLink(grid, Y, X, T);
cout << ans << endl;
return 0;
}