《啊哈!演算法》第4章 萬能的搜尋

OpenSoucre發表於2014-06-22

 

第5節 寶島探險

利用廣度優先搜尋實現

其中可以不用開闢visit變數,直接用將本身的值改為-1,然後判斷即可

注意輸入資料時周圍加了一層-1,作為邊界

廣度優先搜尋

利用深度優先搜尋實現,注意下面的方法是將搜尋到的點著成-1的顏色

深度優先搜尋

注意如果n和m比較大的話,建議用廣度優先搜尋,

由於深度優先搜尋,一直按照深度優先下去,故最壞情況為n*m,

而廣度優先搜尋,的最壞情況是max(n,m)

 關於求小島的數量,只需要對每個點遍歷一邊,如果該點是陸地的話,進行深度優先搜尋

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <utility>
using namespace std;

int dx[] = {-1,0,1,0};
int dy[] = {0,1,0,-1};
typedef pair<int,int> Point;
typedef vector<vector<int> > VectorArray;

void dfs(int x, int y, VectorArray& a){
    for(int i = 0 ; i < 4; ++ i){
        int newx = x+dx[i], newy = y + dy[i];
        if(a[newx][newy] > 0){
            a[newx][newy] = -1;
            dfs(newx,newy,a);            
        }
    }
}

int main(){
    int n,m,x,y;
    cin >> n >> m;
    vector<vector<int> > a(n+2,vector<int>(m+2,-1));
    for(int i = 1 ; i <= n; ++ i){
        for(int j = 1 ; j <= m; ++ j){
            cin >> a[i][j];
        }
    }
    int ans = 0 ;
    for(int i = 1; i <= n; ++ i){
        for(int j  =1; j <= m ; ++ j){
            if(a[x][y] > 0){
                ans++;
                a[x][y]=-1;
                dfs(x,y,a);
            }
        }
    }
    cout<<ans<<endl;
}
求小島的數量

第6節 水管工遊戲 

此題題目感覺非常好,有興趣的話可以先試玩一下水管工遊戲

直管有兩種,進水口有4種可能,上下左右,每種進水口對應的出水口只有一種可能

彎管有4種,進水口有4種可能,上下左右, 每種進水口對應的出水口有兩種可能,因為彎管可以旋轉

然後深度搜尋每種可能

#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
#include <utility>
using namespace std;

typedef pair<int,int> Point;
typedef vector<vector<int> > VVI;
typedef vector<vector<bool> >VVB;

stack<Point> res;
int n,m;
vector<vector<Point> > solutions;
bool flag = false;
void dfs(int x, int y, int direction,VVI& a, VVB& visit){
    if(flag) return;
    if(x == n && y== m+1){
        flag = true;
        while(!res.empty()){
            Point p = res.top();res.pop();
            cout<<"("<<p.first<<","<<p.second<<")->";
        }
        cout<<endl;
        return;
    }
    if(visit[x][y]) return;
    visit[x][y] = true;
    res.push(Point(x,y));
    if(a[x][y] == 5 || a[x][y] == 6){
        switch(direction){
            case 1:dfs(x,y+1,1,a,visit);
            case 2:dfs(x+1,y,2,a,visit);
            case 3:dfs(x,y-1,3,a,visit);
            case 4:dfs(x-1,y,4,a,visit);
        }
    }
    if(a[x][y]>=1 && a[x][y] <= 4){
        switch(direction){
            case 1:{dfs(x+1,y,2,a,visit);dfs(x-1,y,4,a,visit);}
            case 2:{dfs(x,y+1,1,a,visit);dfs(x,y-1,3,a,visit);}
            case 3:{dfs(x-1,y,4,a,visit);dfs(x+1,y,2,a,visit);}
            case 4:{dfs(x,y+1,1,a,visit);dfs(x,y-1,3,a,visit);}
        }
    }
    visit[x][y] = false;
    res.pop();
    return;
}

int main(){
    cin >> n >> m;
    vector<vector<int> > a(n+2,vector<int>(m+2,-1));
    vector<vector<bool> > visit(n+2,vector<bool>(m+2,true));
    for(int i = 1; i <= n ; ++ i){
        for(int j = 1; j <= m ; ++ j){
            cin >> a[i][j];
            visit[i][j] = false;
        }
    }
    dfs(1,1,1,a,visit);
    if(!flag) cout<<"impossible"<<endl;
    
}
水管工遊戲

 

相關文章