我目前正在寻找类似这样的东西:
.............
.............
..XXX.....X..
..XXX.....X..
..XXX........
..XXX........
..XXXXXXX....
..XXXXXXX....
..XXXXXXX....
.............
.............
对此:
.............
.............
..XXX.....O..
..XXX.....O..
..XXX........
..XXX........
..XXXXXXX....
..XXXXXXX....
..XXXXXXX....
.............
.............
用户输入./a.exe input4.txt floodfill 2 10 o
我认为即时通讯将需要对程序实施某种递归,以便仅查看与用户指针匹配的索引(包括上,下,左和右的位置),而不是读取整个矢量(我不介意这样做,但不知道如何开始)。
这是我到目前为止用于洪水填充功能的代码:
void floodfilll(vector<vector<char>> &vec, int x, int y, char r, char dum)
{
int ii;
ii = 0;
int jj;
jj = 0;
for (int i = 0; i < vec.size(); i ++) {
for (int j = 0; j < vec[i].size(); j++) {
if (vec[i][j] == r) {
vec[i][j] == r;
if ((i + ii) > 0) {
if (vec[i-1][j] == r)
vec[i-1][j] = dum;
vec[i][j] == r;
ii--;
floodfilll(vec, x + ii, y, r, dum);
}
if ((j + jj) > 0) {
if(vec[i][j-1] != r)
vec[i][j-1] = dum;
vec[i][j] == r;
jj--;
floodfilll(vec, x, y + jj, r, dum);
}
if ((i + ii)<vec.size()) {
if (vec[i+1][j] != r)
vec[i+1][j] = dum;
vec[i][j] == r;
ii++;
floodfilll(vec, x + ii, y, r, dum);
}
if ((j + jj)<vec[i].size()) {
if (vec[i][j+1] != r)
vec[i][j+1] = dum;
vec[i][j] == r;
jj++;
floodfilll(vec, x, y + jj, r, dum);
}
}
}
replacee(vec, dum, r);
}
}
注意:Im使用名为replacee
的函数将Var dum替换为VarR。Vardum被分配为'i',而r为'X'。
此外,文本文件也被解析为char的 2d向量(char )**
这只是我程序其余部分的基础。这是替换功能:
void replacee(vector<vector<char>> &vec, char oldd, char neww)
{
for (vector<char> &v : vec) // reference to innver vector
{
replace(v.begin(), v.end(), oldd, neww); // standard library algorithm
}
}
这是使用以下命令的int主文件:
int main(int argc, char* argv[]) {
fstream fin; char ch;
string name (argv[1]); //File Name.
vector<vector<char>> data;
// 2D Vector.
vector<char> temp;
// Temporary vector to be pushed
// into vec, since its a vector of vectors.
fin.open(name.c_str(),ios::in);
// Assume name as an arbitary file.
string argument2 (argv[2]);
while(fin)
{
ch = fin.get();
if(ch!='\n') {
temp.push_back(ch);
}
else
{
data.push_back(temp);
temp.clear();
}
}
if (argument2 == "floodfill") {
string argument3 (argv[3]);
string argument4 (argv[4]);
string argument5 (argv[5]);
int x = 0;
int y = 0;
stringstream xx(argument3);
stringstream yy(argument4);
xx >> x;
yy >> y;
floodfilll(data, x, y, argument5[0], 'i');
for (int m = 0; m < data.size(); m ++) {
for (int n = 0; n < data[m].size(); n++) {
cout << data[m][n];
}
cout << endl;
}
}
fin.close();
}
很抱歉,如果我只是粘贴代码以进行抓取,那么这是万一有人在我的思维方式之外有解决方案的情况。 int main
和replacee
函数按预期工作。我只需要帮助,就可以使floodfilll
正常工作。
这是我通过我的代码得到的输出:
$ ./a.exe input4.txt floodfill 2 10 o
.............
.............
..XXX.....X..
..XXX.....X..
..XXX........
..XXX........
..XXXXXXX....
..XXXXXXX....
..XXXXXXX....
.............
答案 0 :(得分:1)
为什么在每次递归中都要遍历整个字段?
通常,洪水填充的工作方式如下:
因此实现可能如下所示:
void floodfill
(
std::vector<std::vector<char>>& v,
unsigned int x, unsigned int y, char r
)
{
char p = v[x][y];
v[x][y] = r;
if(x > 0 && v[x - 1][y] == p)
floodfill(v, x - 1, y, r);
if(x + 1 < v.size() && v[x + 1][y] == p)
floodfill(v, x + 1, y, r);
if(y > 0 && v[x][y - 1] == p)
floodfill(v, x, y - 1, r);
if(y + 1 < v[x].size() && v[x][y + 1] == p)
floodfill(v, x, y + 1, r);
}
请注意,我没有检查要填充的颜色是否与起始像素相同,也没有先检查x
和y
的范围检查。为了提高效率,我不会在递归函数中添加这些检查,而是在启动递归的特定输入函数中添加这些检查,因此它们仅在需要时执行一次,而不必重复执行。
答案 1 :(得分:0)
一个选择是使用递归,如另一个答案所建议。但是,就我个人而言,我更喜欢在不必要的地方避免递归。一种替代方法是基于队列的方法。
void floodfill (std::vector<std::vector<char>>& v, unsigned int x, unsigned int y, char r) {
char init = v[x][y];
if (init == r) return; //We don't want to get caught in an endless loop.
if (x >= v.size() || y >= v[x].size) return; //Index out of bounds.
std::queue<std::pair<unsigned int, unsigned int>> q;
q.push(std::make_pair(x, y)); //Push the initial position into the queue.
v[x][y] = r; //Replace the initial point.
while (!q.empty()) {//Keep looking at relevant neighbours so long as there is something in the queue.
auto pt = q.top(); //Collect the first entry.
q.pop(); //Remove it, we don't want to keep processing the same point.
//Now add neighbours if they match our initial point.
if(pt.first > 0 && v[pt.first - 1][pt.second] == init)
q.push(std::make_pair(pt.first - 1, pt.second);
v[pt.first - 1][pt.second] = r; //Replace the value here to avoid pushing the same point twice.
if(pt.first + 1 < v.size() && v[pt.first + 1][pt.second] == init)
q.push(std::make_pair(pt.first + 1, pt.second);
v[pt.first + 1][pt.second] = r;
if(pt.second > 0 && v[pt.first][pt.second - 1] == init)
q.push(std::make_pair(pt.first, pt.second - 1);
v[pt.first][pt.second - 1] = r;
if(pt.second + 1 < v[pt.first].size() && v[pt.first][pt.second + 1] == init)
q.push(std::make_pair(pt.first, pt.second + 1);
v[pt.first][pt.second + 1] = r;
}
}
这为您提供了类似BFS的泛洪填充模式,而无需递归。或者,您也可以使用stack
而不是queue
,然后,填充将表现得更像DFS(与递归模式将更相似)。鉴于数据结构更简单,它甚至可能比队列更好。