穷搜

深度搜索

POJ 1979

  • POJ 1979题目链接
    这个题目跟找池子差不多 ,而且这个题只要找片同色的瓦块的区域, 很明显的可以用深度搜索。
#include<iostream>
#include<string.h>

using namespace std;

char mat[1002][1002];
int m, n;
int dx[] = {0, 0, -1, 1};
int dy[] = {-1, 1, 0, 0};
int ans;

void dfs(int x, int y){
    mat[x][y] = '#';

    for(int i = 0; i < 4; ++i){
        int gx = x + dx[i], gy = y + dy[i];
        if(0 <= gx && gx < m && 0 <= gy && gy < n
           && mat[gx][gy] == '.'){
               ans++;
               dfs(gx, gy);
           }
    }
    return ;
}

int main(){
    while(cin>>n>>m && m > 0 && n > 0){
        memset(mat, 0, sizeof(mat));
        for(int i = 0; i < m; ++i){
            for(int j = 0; j < n; ++j){
                cin>>mat[i][j];
            }
        }
        ans = 1;
        for(int i = 0; i < m; ++i){
            for(int j = 0; j < n; ++j){
                if(mat[i][j] == '@'){
                    dfs(i, j);
                }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

AOJ0118

  • AOJ 0118题目链接
    这个题目就是把邻近相同的符号化为一块区域, 统计区域数目。
#include<iostream>
#include<string.h>

using namespace std;

char mat[1002][1002];
int m, n;
int dx[] = {0, 0, -1, 1};
int dy[] = {-1, 1, 0, 0};
int ans;


int dfs(int x, int y, char ch){
    mat[x][y] = '.';

    for(int i = 0; i < 4; ++i){
        int gx = x + dx[i], gy = y + dy[i];
        if(0 <= gx && gx < m && 0 <= gy && gy < n
           && mat[gx][gy] == ch){
               dfs(gx, gy, ch);
           }
    }
    return 0;
}

void solve(){
    memset(mat, 0, sizeof(mat));
    for(int i = 0; i < m; ++i){
        for(int j = 0; j < n; ++j){
            cin>>mat[i][j];
        }
    }

    ans = 0;
    for(int i = 0; i < m; ++i){
        for(int j = 0; j < n; ++j){
            if(mat[i][j] != '.'){
                ans++;
                dfs(i, j, mat[i][j]);
            }
        }
    }
    cout<<ans<<endl;
}

int main(){
    while(cin>>m>>n && m > 0 && n > 0){
        solve();
    }
    return 0;
}

AOJ 0033

題意球掉在两个袋子里, 下来的球不能放在比他大的球上, 要求判断10个球能不能按要求下落。
基本思路就是左右比较, 为了突出深度搜索,写成了递归额形式。

#include<iostream>
#include<string.h>

using namespace std;

int a[12];
int n;

bool dfs(int i, int left, int right){
    if(i == 10){
        return true;
    }

    if(a[i] > left && dfs(i + 1, a[i], right)){
        return true;
    }
    if(a[i] > right && dfs(i + 1, left, a[i])){
        return true;
    }
    return false;
}

void solve(){
    for(int i = 0; i < 10; ++i){
        cin>>a[i];
    }

    if(dfs(0, 0, 0)){
        cout<<"YES"<<endl;
    }
    else{
        cout<<"NO"<<endl;
    }
}

int main(){
    cin>>n;
    while(n--){
        solve();
    }
    return 0;
}

AOJ 3009

  • AOJ 3009 题目链接
    扔石头,上下左右四个方向如果某一个方向紧挨着block就不能扔这个方向,否则碰到block停住,block消失,再次四个方向扔。DFS老一套,不过一定要注意判断紧挨着的情况。超过最小步数剪枝也是个很有意思的技巧。
#include<iostream>
#include<string.h>

const int VACANT_TYPE = 0;
const int BLOCK_TYPE = 1;
const int START_TYPE = 2;
const int GOAL_TYPE = 3;
const int MAX_THROW = 10;

using namespace std;

int mat[102][102];
int m, n;
int dx[] = {0, 0, -1, 1};
int dy[] = {-1, 1, 0, 0};
int ans;

void dfs(int x, int y, int step){
    if(step >= MAX_THROW){
        return ;
    }
    for(int i = 0; i < 4; ++i){
        int gx = x, gy = y;
        while(true){
            gx += dx[i], gy += dy[i];

            if(gx < 0 || gx >= m || gy < 0 || gy >= n){
                break;
            }

            if(mat[gx][gy] == GOAL_TYPE){
                ans = min(ans, step + 1);
                break;
            }

            if(mat[gx][gy] == BLOCK_TYPE){
                mat[gx][gy] = VACANT_TYPE;
                int prex = gx - dx[i], prey = gy - dy[i];
                if(!(prex == x && prey == y)){
                    //剪枝
                    dfs(prex, prey, step + 1);
                }
                mat[gx][gy] = BLOCK_TYPE;
                break;
            }
        }
    }
    return ;
}

void solve(){
    ans = 10000;
    memset(mat, -1, sizeof(mat));
    for(int i = 0; i < m; ++i){
        for(int j = 0; j < n; ++j){
            cin>>mat[i][j];
        }
    }
    for(int i = 0; i < m; ++i){
        for(int j = 0; j < n; ++j){
            if(mat[i][j] == START_TYPE){
                dfs(i, j, 0);
            }
        }
    }
    if(ans == 10000){
        ans = -1;
    }
    cout<<ans<<endl;
}


int main(){
    while(cin>>n>>m && n >0 && m > 0){
        solve();
    }
    return 0;
}


广度搜索

AOJ 0558

输入m, n, N, 求 S->1, 1->2, 2->3, ..., 3->N的最短路径。

#include<iostream>
#include<string.h>
#include<queue>

using namespace std;

typedef pair<int, int>P;
int dx[] = {0, 0, -1, 1};
int dy[] = {-1, 1, 0, 0};
int m, n, N;
char mat[1002][1002];
int d[1002][1002];
int ans;

int bfs(int sx, int sy, int goal){
    memset(d, -1, sizeof(d));
    queue<P>que;
    que.push(P(sx, sy));
    d[sx][sy] = 0;

    while(que.size()){
        P p = que.front();
        que.pop();
        int x = p.first, y = p.second;
        if(mat[x][y] == goal){
            return d[x][y];
        }

        for(int i = 0; i < 4; ++i){
            int gx = x + dx[i], gy = y + dy[i];
            if(0 <= gx && gx < m && 0 <= gy && gy < n
               && mat[gx][gy] != 'X' && d[gx][gy] == -1){
                   que.push(P(gx, gy));
                   d[gx][gy] = d[x][y] + 1;
            }
        }
    }
}

void solve(){
    for(int i = 0; i < m; ++i){
        for(int j = 0; j < n; ++j){
            cin>>mat[i][j];
        }
    }

    ans = 0;
    char start = 'S';
    for(int k = 0; k < N; ++k){
        char goal = '1' + k;
        for(int i = 0; i < m; ++i){
            for(int j = 0; j < n; ++j){
                if(mat[i][j] == start){
                    ans += bfs(i, j, goal);
                }
            }
        }
        start = goal;
    }
    cout<<ans<<endl;
}

int main(){
    while(cin>>m>>n>>N && m > 0 && n > 0){
        solve();
    }
    return 0;
}

AOJ 0121


穷竭搜索

原文地址:https://www.cnblogs.com/hichens/p/13332959.html