#c #matrix #graph
#c #матрица #График
Вопрос:
Я пытаюсь сгенерировать график, представляющий все возможные пути из матрицы.
- Возможные пути включают в себя: вверх, вниз, влево, вправо.
- Мой алгоритм пересекает матрицу, но я понял, что это не сработает.
- Хотя код приветствуется, даже идеи или предложения приветствуются. Я просматривал онлайн-ресурсы, но не смог найти примерное решение для этой конкретной проблемы, которое я могу понять.
- Мой код должен выполняться как есть, хотя, конечно, он ошибочен 🙂
C
#include <stdlib.h>
#include <stdio.h>
#include <vector>
struct Tile
{
int tileId;
int moveCost;
};
class Node
{
public:
Node();
void setTile(Tile *tile);
void addLink(Node *node);
private:
std::vector<Node *> mLinks;
Tile *mTile;
};
Node::Node()
{
}
void Node::setTile(Tile *tile)
{
mTile = tile;
}
void Node::addLink(Node *node)
{
mLinks.push_back(node);
}
int main()
{
int boardSize = 5;
std::vector< std::vector<Tile *> > board;
board.resize(boardSize, std::vector<Tile *>(boardSize, NULL));
// generate the board
int i = 0;
for (int x = 0; x < boardSize; x )
{
for (int y = 0; y < boardSize; y )
{
int mc = 1;
if (i == 7 || i == 8 || i == 12 || i == 17 || i == 18)
{
mc = 9;
}
Tile *tile = new Tile();
tile->tileId = i;
tile->moveCost = mc;
board[x][y] = tile;
i ;
}
}
// create graph from the board, with each node having a link to it's nieghboring tile
Node *rootNode = new Node(); // only serves as the entry point
for (int x = 0; x < boardSize; x )
{
for (int y = 0; y < boardSize; y )
{
// this tile node
Node *thisNode = new Node();
thisNode->setTile(board[x][y]);
// up neighbor node
if (y - 1 >= 0)
{
Node *upNode = new Node();
upNode->setTile(board[x][y - 1]);
thisNode->addLink(upNode);
}
// down neighbor node
if (y 1 < boardSize)
{
Node *downNode = new Node();
downNode->setTile(board[x][y 1]);
thisNode->addLink(downNode);
}
// left neighbor node
if (x - 1 >= 0)
{
Node *leftNode = new Node();
leftNode->setTile(board[x - 1][y]);
thisNode->addLink(leftNode);
}
// right neighbor node
if (x 1 < boardSize)
{
Node *rightNode = new Node();
rightNode->setTile(board[x 1][y]);
thisNode->addLink(rightNode);
}
// only add the first node to the rootNode
if (x y == 0)
{
rootNode->addLink(thisNode);
}
}
}
}
Редактировать: например, учитывая эту визуализацию матрицы:
[0][1][2][3][4]
[5][6][7][8][9]
[10][11][12][13][14]
[15][16][17][18][19]
[20][21][22][23][24]
Я бы хотел, чтобы каждый узел графа содержал список указателей на каждого из его соседей (вверх, вниз, влево, вправо)
Tile 0 neighbors: 1,5
Tile 1 neighbors: 0,6,2
Tile 2 neighbors: 1,7,3
И так далее
Комментарии:
1.все возможные пути из матрицы что вы имеете в виду под этим?
2. Я отредактировал свой пост, чтобы включить пример того, что я ищу, надеюсь, это поможет, но если нет, дайте мне знать, и я смогу расширить дальше
3. Почему не a
std::map<int, std::set<int>>
для представления графика? Ключ на карте — это номер плитки, аstd::set<int>
представляет список соседей.4. Еще лучше, потому
node[i][j]
что соседи естьnode[i][j-1], node[i][j 1], node[i-1], node[i 1][j]
…. Вы можете получить соседей за постоянное время, не используя никакой памяти. Вам просто нужно проверить, существуют ли эти индексы или нет
Ответ №1:
Комментарии в коде:
struct MatrixPos {
uint row;
uint col;
};
std::ostreamamp; operator << (std::ostreamamp; o, const MatrixPosamp; p) {
o << "[" << p.row << "," << p.col << "]";
return o;
}
// visit the (tile.row /- 1) and (tile.col /- 1)
// if not out-of-bounds, collect the visited in the neighbours param
void collectNeighbours(
uint numRows, uint numCols,
const MatrixPosamp; tile,
std::vector<MatrixPos>amp; dest
) {
uint nRow=tile.row-1;
uint nCol=tile.col;
if(nRow<numRows) { // otherwise an underflow occurred, so not a neighbour
dest.push_back({nRow, nCol});
}
nRow=tile.row 1;
if(nRow<numRows) dest.push_back({nRow, nCol});
nRow=tile.row;
nCol=tile.col-1;
if(nCol<numCols) dest.push_back({nRow, nCol});
nCol=tile.col 1;
if(nCol<numCols) dest.push_back({nRow, nCol});
}
// convert from {tile.row, tile.col} to linear index
uint tileIndex(const MatrixPosamp; tile, uint numRows) {
return numRows*tile.row tile.col;
}
// convert a linear index to {tile.row, tile.col}
MatrixPos tilePos(uint tileIndex, uint numRows) {
return { tileIndex / numRows, tileIndex % numRows };
}
int main() {
const uint numRows=5, numCols=5;
std::vector<MatrixPos> neighbours;
for(uint i=0; i<numRows*numCols; i ) {
neighbours.clear();
MatrixPos pos=tilePos(i, numRows);
collectNeighbours(numRows, numCols, pos, neighbours);
std::cout << "Tile " << tileIndex(pos, numRows) << " " << pos << " neighbors: ";
// if you need so, convert each {pos->neighbour} into a node
// a Node structure
bool notFirst=false;
for(auto n : neighbours) {
if(notFirst) {
std::cout << ",";
}
notFirst=true;
std::cout << tileIndex(n, numRows);
}
std::cout << std::endl;
}
}
Результат:
Tile 0 [0,0] neighbors: 5,1
Tile 1 [0,1] neighbors: 6,0,2
Tile 2 [0,2] neighbors: 7,1,3
Tile 3 [0,3] neighbors: 8,2,4
Tile 4 [0,4] neighbors: 9,3
Tile 5 [1,0] neighbors: 0,10,6
Tile 6 [1,1] neighbors: 1,11,5,7
Tile 7 [1,2] neighbors: 2,12,6,8
Tile 8 [1,3] neighbors: 3,13,7,9
Tile 9 [1,4] neighbors: 4,14,8
Tile 10 [2,0] neighbors: 5,15,11
Tile 11 [2,1] neighbors: 6,16,10,12
Tile 12 [2,2] neighbors: 7,17,11,13
Tile 13 [2,3] neighbors: 8,18,12,14
Tile 14 [2,4] neighbors: 9,19,13
Tile 15 [3,0] neighbors: 10,20,16
Tile 16 [3,1] neighbors: 11,21,15,17
Tile 17 [3,2] neighbors: 12,22,16,18
Tile 18 [3,3] neighbors: 13,23,17,19
Tile 19 [3,4] neighbors: 14,24,18
Tile 20 [4,0] neighbors: 15,21
Tile 21 [4,1] neighbors: 16,20,22
Tile 22 [4,2] neighbors: 17,21,23
Tile 23 [4,3] neighbors: 18,22,24
Tile 24 [4,4] neighbors: 19,23
Комментарии:
1. Элегантное решение, что более важно, метод понятен мне и, надеюсь, другим. Прими мою благодарность!
2. Пожалуйста. Следующий шаг: оберните его как класс — скажем …
RectangularBoardGeometry
? Затем немного подумайте и поймите, что могут быть и другие геометрии, связанные с соседством, например, гексагональная сетка. Посмотрите, что у них общего и абстрактного. И затем поймите, что могут быть нерегулярные геометрии — как вы могли бы абстрагироваться на один уровень больше, чтобы захватить платы, для которых{row,col}
это не имеет смысла, и все же они все еще могут поддерживать поиск * ? (добро пожаловать в мой — 2D — мир)