简体   繁体   English

2D向量中的C ++回溯

[英]C++ Backtracking in a 2D vector

I am currently trying to use backtracking in order to generate all the different positions a word could have in a 2D vector. 我目前正在尝试使用回溯来生成单词在2D向量中可能具有的所有不同位置。

Let's say that I have a vector (which I prefer to use for memory reasons as I will be treating a lot of words) containing the word 'Hello'. 假设我有一个向量(我出于记忆的原因更喜欢使用它,因为我将处理很多单词)包含单词“ Hello”。

I generate a 2D vector of '.' 我生成一个2D向量。 characters 5x5 wide (so it can fit the word). 5x5宽的字符(因此可以容纳单词)。

And then using a backtracking algorithm, I would like to generate all the positions this word could take with the letters still linked to each other . 然后,使用回溯算法,我想生成该单词在字母仍然彼此链接的情况下可以占据的所有位置。

For example : 例如 :

 . . . . .        . . . . .              . . . . .
 H e . . .   or   . . . H .    or even   . . . . .
 . l . . .        . . o e .              . . . . .
 . l o . .        . . l l .              . . . . .
 . . . . .        . . . . .              o l l e H

The algorithm I am interested in for 1D is (pseudo code): 我对一维感兴趣的算法是(伪代码):


function solve(word vector, size of vector) 

  if end of word vector
     Print vector obtained

   else for choice possible do
         if Choice is admissible then 
             Build partial Candidate according to Choice 
             Test(i + 1) 
             Undo Choice

This pseudo code could give the different combinations of letters in a word. 该伪代码可以给一个单词提供字母的不同组合。 I'm trying to adapt it to make it do what explained before. 我正在尝试对其进行调整,以使其按照之前的说明进行操作。

Sadly I'm implementing it wrong because I don't obtain the results expected at all : Nothing prints. 遗憾的是,我实施错了,因为我根本没有获得预期的结果:什么也没打印。 I would be pleased to read your remarks and opinions on this. 我很高兴阅读您对此的评论和意见。

Here is what I did so far : 这是我到目前为止所做的:

Backtracking function : 回溯功能:

// All the arguments of the function are correctly defined in the main, with i, j, k set to zero.

bool backtracking(vector<vector<char> > vect , vector <char> word,int n, int i, int j, int k) {

    if(k==n)    // If the end of the word is reached
    {
        print_grid(vect);  //Prints the 2D vector with the word included
        return true;
    }

    else    
    {

        if(admissible_choice(vect, n, i, j) == true) // If choice is admissible
        {

            vect[i][j] = word[k];                   // Builds partial candidate

            if (backtracking(vect,word,n,i+1,j,k)==true) // Moves in the i-direction
            {   k++;                    // If true, goes to the next element of the chain
                return true;        }

            if (backtracking(vect,word,n,i,j+1,k)==true) // Moves in the j direction
            {   k++;
                return true;        }

            else
            {   vect[i][j] = '.';           // Backtrack, if no condition verified then fills the 2D vector with points

                return false;       }
        }

    return false;
    }

}   

Printing function 打印功能

void print_grid(vector<vector<char> > vect) {
    for (int i = 0; i < vect.size(); i++)  {
        for (int j = 0; j < vect[i].size(); j++) {
            cout << vect[i][j]; 
        }
        cout<<""<<endl;
    }
    cout<<"\n"<<endl;   
}

Function to determine admissible choices 确定可接受选择的功能

bool admissible_choice(vector<vector<char> > vect, int n, int i, int j)
{
    if(i >= 0 && i < n && j >= 0 && j < n && vect[i][j] == '.')
    {   return true;}

    else
    {   return false;}
}

Thanks in advance for all the help you could provide ! 预先感谢您可以提供的所有帮助!

Here you go. 干得好。 There is a fundamental difference between kicking off the search at some point, and proceeding from one valid point to the next point. 从某个时刻开始搜索到从一个有效点进行到下一个点之间存在根本的区别。 So in this code, place_word iterates through all possible grid positions, calling the recursive backtracking for each point. 因此,在此代码中, place_word遍历所有可能的网格位置,并为每个点调用递归backtracking

backtracking needs to search, not just the incremented coordinates, but also the decremented coordinates. backtracking需要搜索增加的坐标,还需要搜索减少的坐标。 Where place_word only increments its coordinates -- I think your original attempt was trying to combine these concepts into one unit of code. 其中place_word仅增加其坐标-我认为您最初的尝试是尝试将这些概念组合为一个代码单元。

I also chose to pass the 2D grid vector by reference and undo any changes made by the recursive function before it returns. 我还选择通过引用传递2D网格矢量,并在递归函数返回之前撤消对递归函数所做的任何更改。 This way, only one grid object is used by the search, while passing by value incurs a lot of overhead by making a new copy of the grid each time backtracking is called. 这样,搜索仅使用一个网格对象,而每次调用backtracking时,按值传递都会通过创建新的网格副本而产生大量开销。

I needed to rename some of the variables to help me understand what was going on. 我需要重命名一些变量以帮助我了解发生了什么。 I also removed dimension variables which were redundant because they were already available as vector sizes. 我还删除了多余的尺寸变量,因为它们已经可以用作矢量尺寸。

#include <iostream>
#include <vector>
#include <algorithm>

// admissible_choice returns true when the point at (x,y) is inside the grid,
// and is also unpopulated.
bool admissible_choice(std::vector<std::vector<char> > grid, int x, int y) {
    return x >= 0
        && x < static_cast<int>(grid.front().size())
        && y >= 0
        && y < static_cast<int>(grid.size())
        && grid[y][x] == '.';
}

void print_grid(std::vector<std::vector<char> > const& grid) {
    for(const auto& line : grid) {
        for(auto ch : line) {
            std::cout << ch;
        }
        std::cout << '\n';
    }
    std::cout << '\n';
}

// backtracking performs a depth-first recursive search for valid word positions
void backtracking(std::vector<std::vector<char> > &grid, std::vector<char> const& word, int x, int y, int wi=0) {
    if(!admissible_choice(grid, x, y)) {
        return;
    }

    grid[y][x] = word[wi];

    if(++wi == word.size()) {
        print_grid(grid);
    } else {
        backtracking(grid, word, x+1, y, wi);
        backtracking(grid, word, x-1, y, wi);
        backtracking(grid, word, x, y+1, wi);
        backtracking(grid, word, x, y-1, wi);
    }
    grid[y][x] = '.';
}

// place_word initializes backtracking recursion, for every
// possible starting point for a word placed in a grid
void place_word(std::vector<std::vector<char> > &grid, std::vector<char> const& word) {
    const int width = static_cast<int>(grid.front().size());
    const int height = static_cast<int>(grid.size());
    for(int y=0; y<height; ++y) {
        for(int x=0; x<width; ++x) {
            backtracking(grid, word, x, y);
        }
    }
}

// ToVector converts a char string literal to a vector
template <std::size_t N>
std::vector<char> ToVector(const char (&str)[N]) {
    return std::vector<char>(&str[0], &str[N-1]);
}

// InitGrid returns a grid with the given dimensions in its unpopulated state
std::vector<std::vector<char> > InitGrid(std::size_t width, std::size_t height) {
    std::vector<std::vector<char> > grid(height);
    for(auto& line : grid) {
        line.assign(width, '.');
    }
    return grid;
}

int main() {
    auto word = ToVector("Hello");
    auto grid = InitGrid(word.size(), word.size());

    place_word(grid, word);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM