假设有一个矩阵
1 1 0 0 0
0 1 1 0 0
1 0 1 1 0
0 1 1 0 0
0 0 1 1 1
并要求找到路径仅从左上角(粗体斜体1)到右下角(另一个类似的1)传递 。一旦这样的路径以粗体显示。
我一直在尝试用C ++实现这个,但我很惊讶 - segfaulting。更重要的是,我无法在不重复大量代码的情况下解决任何问题。
这是我的代码:
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <list>
using namespace std;
typedef pair<int, int> Coords;
struct Point {
int x, y;
int val;
bool visited;
Point (int a, int b, int v) : x(a), y(b), val(v), visited(false) {}
};
int main() {
int n;
cin >> n;
vector<vector<Point> > pts(n, vector<Point>(n, Point(0, 0, 0)));
int temp = 0;
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
cin >> temp;
pts[i][j] = Point(i, j, temp);
}
}
queue<Coords> toVisit;
toVisit.push(Coords(0,0));
Coords cur(0, 0);
vector<Coords> neighbors;
while(!toVisit.empty()) {
cur = toVisit.back();
toVisit.pop();
int x = cur.first, y = cur.second;
pts[x][y].visited = true;
bool xgt0 = x > 0, xltm = x < n;
bool ygt0 = y > 0, yltm = y < n;
// x-1,y-1 x ,y-1 x+1,y-1
// x-1,y x ,y x+1,y
// x-1,y+1 x ,y+1 x+1,y+1
if(xgt0) {
if(!pts[x-1][y].visited) toVisit.push(Coords(x-1,y));
if(ygt0 && !pts[x-1][y-1].visited) toVisit.push(Coords(x-1,y-1));
if(yltm && !pts[x-1][y+1].visited) toVisit.push(Coords(x-1,y+1));
}
if(ygt0 && !pts[x][y-1].visited) toVisit.push(Coords(x,y-1));
if(yltm && !pts[x][y+1].visited) toVisit.push(Coords(x,y+1));
if(xltm) {
if(!pts[x+1][y].visited) toVisit.push(Coords(x+1,y));
if(ygt0 && !pts[x+1][y-1].visited) toVisit.push(Coords(x+1,y-1));
if(yltm && !pts[x+1][y+1].visited) toVisit.push(Coords(x+1,y+1));
}
}
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
cout << pts[i][j].visited << " ";
}
cout << endl;
}
}
根本不起作用。我该如何解决这个问题?
如何编写此程序而不在BFS邻居添加段中复制如此多的代码?
解决了,这是代码(现在完全解决了原始问题)。
进行了一些重构以减少代码重复,但可以做更多的事情,例如将if(something && proceed(...)) push(...)
转换为if(something) pushIfOK(...)
。对于喜欢冒险的读者来说,这只是一个练习,只需要比我现在更多的时间。 :)
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <list>
using namespace std;
typedef pair<int, int> Coords;
struct Point {
int x, y;
bool val; //passable or not?
bool visited;
Point (int a, int b, bool v) : x(a), y(b), val(v), visited(false) {}
};
bool proceed(Point);
int main() {
int n;
cin >> n;
vector<vector<Point> > pts(n, vector<Point>(n, Point(0, 0, true)));
int temp = 0;
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
cin >> temp;
pts[i][j] = Point(i, j, temp == 1);
}
}
queue<Coords> toVisit;
toVisit.push(Coords(0,0));
Coords cur(0, 0);
vector<Coords> neighbors;
while(!toVisit.empty()) {
cur = toVisit.back();
toVisit.pop();
int x = cur.first, y = cur.second;
pts[x][y].visited = true;
bool xgt0 = x > 0, xltm = x < n - 1;
bool ygt0 = y > 0, yltm = y < n - 1;
// x-1,y-1 x ,y-1 x+1,y-1
// x-1,y x ,y x+1,y
// x-1,y+1 x ,y+1 x+1,y+1
if(ygt0 && proceed(pts[x][y-1])) toVisit.push(Coords(x,y-1));
if(yltm && proceed(pts[x][y+1])) toVisit.push(Coords(x,y+1));
if(xgt0) {
if(proceed(pts[x-1][y])) toVisit.push(Coords(x-1,y));
if(ygt0 && proceed(pts[x-1][y-1])) toVisit.push(Coords(x-1,y-1));
if(yltm && proceed(pts[x-1][y+1])) toVisit.push(Coords(x-1,y+1));
}
if(xltm) {
if(proceed(pts[x+1][y])) toVisit.push(Coords(x+1,y));
if(ygt0 && proceed(pts[x+1][y-1])) toVisit.push(Coords(x+1,y-1));
if(yltm && proceed(pts[x+1][y+1])) toVisit.push(Coords(x+1,y+1));
}
}
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
cout << pts[i][j].visited << " ";
}
cout << endl;
}
}
bool proceed(Point p) { return p.val && !p.visited; }
答案 0 :(得分:0)
我一直在尝试用C ++实现这个,但我 - 惊讶 - segfaulting。
您的segfaults问题是由于高价值检查:
if (yltm && !pts[x][y+1].visited) toVisit.push(Coords(x,y+1));
请注意,当y = n - 1
yltm == true
并且您尝试访问数组中的pts[x][n]
条目时,该条目不存在(其位置为n + 1,基于零的索引以及全部)
不幸的是,由于输入数据的性质,您需要检查边界并拥有所有重复的代码,但我不认为在这种情况下您可以避免它。在修复segfaulting并继续尝试找到角落之间的实际路径之后的提示:尝试跟踪搜索的“深度”并使用它来查找从右下角返回到左上角的路径。