DFS解决海岸线长度的麻烦

时间:2016-09-16 07:25:44

标签: c++ depth-first-search

我试图解决一个问题,我在网站https://open.kattis.com/problems/coast找到了这个问题。 Tl; dr版本的问题是,对于给定的景观地图,我应该打印出海岸线的长度(没有内岛)。

我的想法是,通过添加额外的图层然后启动DFS来解决这个问题,因此算法将遍历地图中的每个可能的图块,然后在每个图块上观察图块周围有多少个边框。

但是,对于特定输入,我的算法不起作用。当我在这个网站(open.kattis)上提交解决方案时,它说,我的程序在26个测试中的第9个中给出了错误的答案(前8个测试没问题),但没有任何进一步的解释。

有人可以看看我的节目,然后说我,为什么不好?我哪里弄错了?感谢

#include <iostream>
#include <stack>
#include <sstream>

using namespace std;

int main() {
    string line;
    getline(cin, line);

    int rows = 0;
    int columns = 0;

    stringstream stream(line);
    stream >> rows;
    stream >> columns;

    int map[rows][columns];

    for (int i = 0; i < rows; i++) {
        getline(cin, line);
        for (int j = 0; j < columns; j++) {
            map[i][j] = line[j] - 48;
        }
    }
    //parsed landscape into 2d array

//    int rows = 5;
//    int columns = 6;
//    int map[rows][columns] = {
//            {0, 1, 1, 1, 1, 0,},
//            {0, 1, 0, 1, 1, 0,},
//            {1, 1, 1, 0, 0, 0,},
//            {0, 0, 0, 0, 1, 0,},
//            {0, 0, 0, 0, 0, 0,},
//    };

int bigMap[rows+2][columns+2];
bool visited[rows+2][columns+2];

//create bigger map, so DFS can start from corner and assume
//that there is water around everywhere
//also initialize array visited for DFS

//add 2 new rows, before and after existing one
for (int i = 0; i < columns+2; i++) {
    bigMap[0][i] = 0;
    bigMap[rows + 1][i] = 0;

    visited[0][i] = false;
    visited[rows + 1][i] = false;
}

//add 2 new columns, before and after existing
//copy original map to new one
for (int i = 0; i < rows; i++) {
    bigMap[i+1][0] = 0;
    bigMap[i+1][columns + 1] = 0;

    visited[i+1][0] = false;
    visited[i+1][columns + 1] = false;
    for (int j = 0; j < columns; j++) {
        bigMap[i+1][j+1] = map[i][j];

        visited[i+1][j+1] = false;
    }
}
rows += 2;
columns += 2;

//starting DFS
int x = 0, y = 0;
//visited[x][y] = true; <-- edit
pair <int, int> coordinates;

coordinates.first = x;
coordinates.second = y;

stack<pair <int, int> > st;

//first vertex in stack
st.push(coordinates);

//total sum of borders
int borders = 0;

while(!st.empty()) {
    //check coordinates in each round
    x = st.top().first;
    y = st.top().second;

    //navigate to new vertex (only if new vertex wasn't visited (visited[x][y] == 0) and only
    //if there is water (bigMap[x][y] == 0) and check if new vertex is still in the map
    //if there is no possible vertex, then we reached the end so then pop the vertex and
    //look in another way
    if (visited[x][y+1] == 0 && bigMap[x][y+1] == 0 && y + 1 < columns) {
        y++;
        coordinates.second = y;
        st.push(coordinates);
    } else {
        if (visited[x+1][y] == 0 && bigMap[x+1][y] == 0 && x + 1 < rows) {
            x++;
            coordinates.first = x;
            st.push(coordinates);
        } else {
            if (visited[x][y-1] == 0 && bigMap[x][y-1] == 0 && y > 0) {
                y--;
                coordinates.second = y;
                st.push(coordinates);
            } else {
                if (visited[x-1][y] == 0 && bigMap[x-1][y] == 0 && x > 0) {
                    x--;
                    coordinates.first = x;
                    st.push(coordinates);
                } else {
                    st.pop();
                    continue;
                }
            }
        }
    }
    //visited new vertex, so look around him and count borders
    visited[x][y] = true;
    if (bigMap[x][y+1] == 1 && y + 1 < columns) borders++;
    if (bigMap[x+1][y] == 1 && x + 1< rows) borders++;
    if (bigMap[x][y-1] == 1 && y > 0) borders++;
    if (bigMap[x-1][y] == 1 && x > 0) borders++;
}
cout << borders << endl;

return 0;

2 个答案:

答案 0 :(得分:0)

我认为{1,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}会失败。这是因为由于顶点0,0的设置visited = true,因此无法完成漫游。将它设为false为0,0而不是改进的东西。希望它有所帮助。

答案 1 :(得分:0)

问题是您每次在循环周围重复使用变量coordinates而不将其设置为正确的值。您的if测试级联假设coordinates设置为当前位置。只有在降级dfs时才会出现这种情况。一旦你再次开始提升,coordinate将指向错误的位置。

简单解决方案,添加

    coordinates = st.top();

在你的循环顶部。

以下是目前出错的示例地图。

5 6
000000
011100
001010
000100
000000

答案应该是14,但是目前你得到18,因为程序到达第3行第4列的湖泊。

要检查它是否正在执行此操作,请在循环的末尾添加一个调试行,以便添加边框。

cout << "adding " << x << " " << y << "\n"; 

然后,您可以验证该程序是否正在考虑它不应该使用的任何位置。