• SDNU-ACM-ICPC 2020 DFS&BFS (咕咕o(≧v≦)o)


    传送门

    Red and Black

    题意:

    m * n的地图,#不可以走,.可以走,@是起点,问你从@开始能走到的点的个数是多少

    方法1:dfs

    这个题相当于问的是从起点开始能走到的位置,跟路径没有关系,只要dfs整个地图就可以,而且每个点只需要走一遍,我们就判断如果是‘.’并且没被标记过,就更新答案,然后标记一下

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    int n, m, xx, yy, ans;
    char tr[25][25];
    int dx[] = {1, 0, -1, 0};
    int dy[] = {0, -1, 0, 1};
    bool vis[25][25];
    
    void dfs(int x, int y){
        if(tr[x][y] == '.' && vis[x][y] == 0){
            ans++;
            vis[x][y] = 1;
        }
        else return;
        for(int i = 0; i < 4; ++i){
            xx = x + dx[i];
            yy = y + dy[i];
            dfs(xx, yy);
        }
    }
    
    int main(){
        while(cin>>n>>m && n != 0 && m != 0){
            memset(tr, 0, sizeof(tr));
            memset(vis, 0, sizeof(vis));
            ans = 0;
            swap(n, m);//本题是m行n列,将其转化成n行m列会好写点
            for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j){
            scanf(" %c",&tr[i][j]);
                if(tr[i][j] == '@'){
                    xx = i; yy = j;
                    tr[i][j] = '.';
                }
            }
            dfs(xx, yy);
            cout<<ans<<endl;
        }
        return 0;
    }
    

    方法2:bfs

    因为每个点只走一遍,就很符合bfs的特点

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    int n, m, xx, yy, ans;
    char tr[25][25];
    int dx[] = {1, 0, -1, 0};
    int dy[] = {0, -1, 0, 1};
    bool vis[25][25];
    struct ran{
        int x, y;
    };
    queue<ran>q;
    bool judge(int x, int y){
        if(x > n || x < 1 || y > m || y < 1)return false;
        else if(vis[x][y])return false;
        else if(tr[x][y] == '#')return false;
        else return true;
    }
    
    void bfs(){
        ran now, next;
        now.x = xx; now.y = yy;
        q.push(now);
        vis[now.x][now.y] = 1;
        while (!q.empty()) {
            now = q.front();q.pop();
            if(tr[now.x][now.y] == '.'){
                ans++;
            }
            for(int i = 0; i < 4; ++i){
                next.x = now.x + dx[i];
                next.y = now.y + dy[i];
                if(!judge(next.x, next.y))continue;
                vis[next.x][next.y] = 1;
                q.push(next);
            }
            
        }
    }
    
    int main(){
        while(cin>>n>>m && n != 0 && m != 0){
            memset(tr, 0, sizeof(tr));
            memset(vis, 0, sizeof(vis));
            ans = 0;
            swap(n, m);
            for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j){
            scanf(" %c",&tr[i][j]);
                if(tr[i][j] == '@'){
                    xx = i; yy = j;
                    tr[i][j] = '.';
                    vis[i][j] = 1;
                }
            }
            bfs();
            cout<<ans<<endl;
        }
        return 0;
    }
    

    B - 棋盘问题

    题意:

    在给定棋盘上放棋子,其中#位置不能放,且你放的所有的棋子中的任意两个,不能在同一行或同一列,问你总共有多少种摆法

    思路:

    这个题只能dfs,按行搜,

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    int n, k, xx, yy, ans, step;
    bool vis[10];
    char tr[10][10];
    bool judge(int x, int y){
        if(x > n || x < 1 || y > n || y < 1)return false;
        else if(tr[x][y] == '#')return false;
        else return true;
    }
    void dfs(int x){
        if(step == k){
            ans++;
            return;
        }
        if(x > n)return;//这个和下面的那个是配对的,当你一直跳到下一行就可以会跳出去了
        for(int y = 1; y <= n; ++y){
            if(judge(x, y))continue;
            if(vis[y])continue;
            vis[y] = 1;
            step++;
            dfs(x + 1);
            step--;
            vis[y] = 0;
        }
        dfs(x + 1);//可能这个行没有点可以用,就得手动跳到下一行
    }
    
    int main(){
        while (cin>>n>>k && n != -1 && k != -1) {
            memset(tr, 0, sizeof(tr));
            memset(vis, 0, sizeof(vis));
            ans = 0;
            for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
            scanf(" %c",&tr[i][j]);
            dfs(1);
            cout<<ans<<endl;
        }
    }
    
    

    C - Dungeon Master

    题意:

    三维迷宫,问你能不能从S走到E,只能上下左右前后走,而且不能走#格

    思路:

    bfs就完事了,输入的是一层一层的,所以对于xyz会有点奇怪

    一定一定一定一定一定要记得给他么的狗队列清0 ,不然会wa的很惨(只有亲身经历后才知道有多崩溃!呜呜呜)

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    int h, n, m, xx, yy, zz, ans;//h是高度,n是行数,m是列数
    char tr[35][35][35];
    bool vis[35][35][35];
    int dx[] = {1, 0, -1, 0, 0, 0};
    int dy[] = {0, 1, 0, -1, 0, 0};
    int dz[] = {0, 0, 0, 0, 1, -1};
    bool judge(int z, int x, int y){
        if(z > h || z < 1 || x > n || x < 1 || y > m || y < 1)return false;
        else if(vis[z][x][y])return false;
        else if(tr[z][x][y] == '#')return false;
        else return true;
    }
    struct ran{
        int x, y, z, step;
    };
    queue<ran>q;//千万千万要给队列初始化!
    
    int  bfs(){
        ran now, next;
        now.z = zz;now.x = xx;now.y = yy;now.step = 0;
        q.push(now);
        vis[now.z][now.x][now.y] = 1;
        while (!q.empty()) {
            now = q.front();
            q.pop();
            if(tr[now.z][now.x][now.y] == 'E'){
                return now.step;
            }
            for(int i = 0; i < 6; ++i){
                next.z = now.z + dz[i];
                next.x = now.x + dx[i];
                next.y = now.y + dy[i];
                if(!judge(next.z, next.x, next.y))continue;
                vis[next.z][next.x][next.y] = 1;
                next.step = now.step + 1;
                q.push(next);
            }
        }
        return 0;
    }
    
    int main(){
        while (cin>>h>>n>>m && (h + n + m)) {
            memset(tr, 0, sizeof(tr));
            memset(vis, 0, sizeof(vis));
            while (!q.empty()) {//千万要给队列初始化!
                q.pop();
            }
            ans = 0;
            for(int i = 1; i <= h; ++i)
            for(int j = 1; j <= n; ++j){
            scanf(" %s",tr[i][j] + 1);
            for(int k = 1; k <= m; ++k){
                if(tr[i][j][k] == 'S'){
                    zz = i;xx = j;yy = k;
                    tr[i][j][k] = '.';
                }
            }
            }
            ans = bfs();
            if(ans)
                printf("Escaped in %d minute(s).
    ",ans);
            else
                printf("Trapped!
    ");
        }
        return 0;
    }
    

    D - Catch That Cow

    题意:

    在0到1e5的道路上,农夫要去抓牛,牛不动,农夫可以在一分钟内可以向前移动一格或者向后移动一个,或者到达2倍位置的地方,问最短多长时间抓到牛

    思路:

    一维bfs,注意不能走重复,因为如果重复了就代表这绝对不是最短距离

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    int n, k;
    bool vis[MAX];
    struct ran{
        int x, step;
    };
    queue<ran>q;
    
    bool judge(int x){
        if(x > 1000001 || x < 0)return false;
        else if(vis[x])return false;
        else return true;
    }
    
    int bfs(){
        ran now, next;
        now.x = n;now.step = 0;
        q.push(now);
        vis[now.x] = 1;
        while (!q.empty()) {
            now = q.front();q.pop();
            if(now.x == k){
                return now.step;
            }
            next.x = now.x * 2;next.step = now.step + 1;
            if(judge(next.x)){
                q.push(next);
                vis[next.x] = 1;
            }
                
            next.x = now.x - 1; next.step = now.step + 1;
            if(judge(next.x)){
                q.push(next);
                vis[next.x] = 1;
            }
            next.x = now.x + 1; next.step = now.step + 1;
            if(judge(next.x)){
                q.push(next);
                vis[next.x] = 1;
            }
        }
        return 0;
    }
    
    int main(){
        cin>>n>>k;
        cout<<bfs()<<endl;
    }
    

    G - 胜利大逃亡

    题意:

    三维地图,问你能不能在规定时间内从(1,1,1)走到(h, n, m)

    思路:

    三维bfs即可,同样的xyz的顺序不是那么顺

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    int T, n, m, h, t;
    int tr[55][55][55];
    bool vis[55][55][55];
    int dx[] = {1, 0, -1, 0, 0, 0};
    int dy[] = {0, 1, 0, -1, 0, 0};
    int dz[] = {0, 0, 0, 0, 1, -1};
    struct ran{
        int x, y, z, step;
    };
    queue<ran>q;
    bool judge(int z, int x, int y){
        if(z > h || z < 1 || x > n || x < 1 || y > m || y < 1)return false;
        else if(vis[z][x][y])return false;
        else if(tr[z][x][y] == 1)return false;
        else return true;
    }
    
    void init(){//初始化
        memset(tr, 0, sizeof(tr));
        memset(vis, 0, sizeof(vis));
        while (!q.empty()) {
            q.pop();
        }
    }
    
    int bfs(){
        ran now, next;
        now.x = 1;now.y = 1;now.z = 1;now.step = 0;
        q.push(now);
        vis[1][1][1] = 1;
        while (!q.empty()) {
            now = q.front();q.pop();
            if(now.z == h && now.x == n && now.y == m){
                return now.step;
            }
            for(int i = 0; i < 6; ++i){
                next.z = now.z + dz[i];next.x = now.x + dx[i];next.y = now.y + dy[i];
                if(!judge(next.z, next.x, next.y))continue;
                vis[next.z][next.x][next.y] = 1;
                next.step = now.step + 1;
                q.push(next);
                }
        }
        return 0;
    }
    
    int main(){
        cin>>T;
        while (T--) {
            init();
            cin>>h>>n>>m>>t;
            for(int i = 1; i <= h; ++i)
            for(int j = 1; j <= n; ++j)
            for(int k = 1; k <= m; ++k)
            tr[i][j][k] = IntRead();
            int ans = bfs();
            if(ans != 0 && ans <= t)cout<<ans<<endl;
            else cout<<-1<<endl;
            
        }
    }
    

    H - A计划

    题意:

    在三维图内救公主,从(0,0,0)出发,不能走*,遇到#就会传送到另一层的同一个位置,如果传送过去的地方是#就会直接撞死,问你能不能在t时刻找到公主

    思路:

    bfs,遇到传送门就得特判,另一层的同一个位置不可以是*或#

    这个题说的是能不能在t时刻找到公主,但ac码是能不能在t时刻之前找到,我就有点懵o(︶︿︶)o

    还有就是最后输出的是YES和NO,而不是最短时间!靠

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    int T, n, m, h, t, xx, yy, zz;
    char tr[5][55][55];
    bool vis[5][55][55];
    int dx[] = {1, 0, -1, 0};
    int dy[] = {0, 1, 0, -1};
    struct ran{
        int x, y, z, step;
    };
    queue<ran>q;
    
    bool judge(int z, int x, int y){
        if(x > n || x < 1 || y > m || y < 1 || z < 1 || z > 2)return false;
        else if(vis[z][x][y])return false;
        else if(tr[z][x][y] == '*')return false;
        else return true;
    }
    
    void init(){
        memset(tr, 0, sizeof(tr));
        memset(vis, 0, sizeof(vis));
        while (!q.empty()) {
            q.pop();
        }
    }
    
    int bfs(){
        ran now, next;
        now.z = zz;now.x = xx;now.y = yy;now.step = 0;
        q.push(now);vis[zz][xx][yy] = 1;
        while (!q.empty()) {
            now = q.front();q.pop();
            if(tr[now.z][now.x][now.y] == 'P'){
                return now.step;
            }
            for(int i = 0; i < 4; ++i){
                next.z = now.z;next.x = now.x + dx[i];next.y = now.y + dy[i];
                if(tr[next.z][next.x][next.y] == '#'){
                    if(next.z == 1)next.z++;
                    else if(next.z == 2)next.z--;
                    if(tr[next.z][next.x][next.y] == '#')continue;
                    if(!judge(next.z, next.x, next.y))continue;
                    vis[next.z][next.x][next.y] = 1;
                    next.step = now.step + 1;
                    q.push(next);
                }
                else {
                    if(!judge(next.z, next.x, next.y))continue;
                    vis[next.z][next.x][next.y] = 1;
                    next.step = now.step + 1;
                    q.push(next);
                }
            }
        }
        return 0;
    }
    
    
    int main(){
        cin>>T;
        while (T--) {
            init();
            cin>>n>>m>>t;
            //cout<<n<<m<<t;
            for(int i = 1; i <= 2; ++i)
            for(int j = 1; j <= n; ++j)
            for(int k = 1; k <= m; ++k){
                scanf(" %c",&tr[i][j][k]);
                if(tr[i][j][k] == 'S'){
                    zz = i;xx = j; yy = k;
                }
            }
            int ans = bfs();
            if(ans != 0 && ans <= t)
                cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
            
        }
        return 0;
    }
    
    

    I - Sum It Up

    题意:

    m个数,从中找任意多个数,要保证其和等于n,且不重复的情况的个数,并降序输出每种情况,每种情况也是降序输出

    思路:

    首先因为要降序输出,所以得对数列进行降序排列,然后通过dfs进行搜索,两个变量:star表示走到了哪个位置,sum表示到目前为止的和

    最重要的其实是去重,这里通过star来控制就能实现,同时对于每次return后要去掉这之后所有与他相同的数字

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    int n, m, num, ans;
    int tr[100], ar[100];
    bool vis[100];
    
    void init(){
        memset(tr, 0, sizeof(tr));
        memset(vis, 0, sizeof(vis));
        memset(ar, 0, sizeof(ar));
        ans = 0;num = 0;
    }
     
    bool cmp(int x, int y){
        return x > y;
    }
    
    void dfs(int star, int sum){
        if(sum > n)return;
        else if(sum == n){
            ans = 1;
            for(int i = 1; i <= num; ++i){
                if(i != num)cout<<ar[i]<<'+';
                else cout<<ar[i]<<endl;
            }
        }
        for(int i = star; i <= m; ++i){
            ar[++num] = tr[i];
            vis[i] = 1;
            dfs(i + 1, sum + tr[i]);
            vis[i] = 0;
            num--;
            while (i + 1 <= m && tr[i] == tr[i + 1]) {
                i++;
            }
        }
    }
    
    int main(){
        while (cin>>n>>m && (n + m)) {
            init();
            for(int i = 1; i <= m; ++i)cin>>tr[i];
            sort(tr + 1, tr + 1 + m, cmp);
            printf("Sums of %d:
    ",n);
            dfs(1, 0);
            if(!ans)cout<<"NONE
    ";
        }
    }
    
    

    J - N皇后问题

    思路:

    两个皇后不能在行或列或对角线上,对角线有两个,我们还是同B题一样按行搜,对每行的列进行dfs,这次vis数组要开二维的,好记录列与两个对角线是否标记过,对于对角线相当于一个一次函数,而我们标记的是他的y = kx + b中的b,k = 1或-1,b就等于x + y或 x - y,但是x - y可能会出现负数,所以我们可以加上n,这样就可以保证下标大于0,但是要给数组开的稍微大一点点,这个数n + x - y最大是20,超过20就可以(我第一遍开了个15,就直接wa了,艹),再就是要注意用数组存答案,然后人家问什么就直接输出

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    int n, tr[15];
    bool vis[3][100];
    void init(){
        memset(vis, 0, sizeof(vis));
        
    }
    
    bool judge(int x, int y){
        if(vis[0][y])return false;
        else if(vis[1][x + y])return false;
        else if(vis[2][n + x - y])return false;
        else return true;
    }
    
    void dfs(int x){
        if(x == n){
            tr[n]++;
            return;
        }
        for(int y = 1; y <= n; ++y){
            if(!judge(x, y))continue;
            vis[0][y] = 1;
            vis[1][x + y] = 1;
            vis[2][n + x - y] = 1;
            dfs(x + 1);
            vis[0][y] = 0;
            vis[1][x + y] = 0;
            vis[2][n + x - y] = 0;
        }
    }
    
    int main(){
        for(int i = 1; i <= 10; ++i){
            n = i;
            init();
            dfs(0);
        }
        while (cin>>n && n) {
            cout<<tr[n]<<endl;
        }
    }
    
    

    K - Oil Deposits

    题意:

    给你一个地图,@代表油田,其他点代表石头,问你总共有几个油田,其中一个点可以和周围八个点相连

    思路1:

    dfs:直接怼暴力,搜整个图,遇到一个@且未经过标记的就开始dfs,dfs的时候要对所有相连的@进行标记,最好输出ans即可

    注意,这次dfs要在刚开始就标记,因为如果写在循环判断后面,就可能你搜 的点是@但周围八个点全是石头,就不会更新答案滴

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    char tr[105][105];
    bool vis[105][105];
    int n, m, ans, cnt;
    int dx[] = {1, 0, -1, 0, -1, 1, 1, -1};
    int dy[] = {0, 1, 0, -1, -1, 1, -1, 1};
    
    
    void init(){
        memset(vis, 0, sizeof(vis));
        memset(tr, 0, sizeof(tr));
        ans = 0;
    }
    
    bool judge(int x, int y){
        if(x > n || x < 1 || y > m || y < 1)return false;
        else if(vis[x][y])return false;
        else if(tr[x][y] == '*')return false;
        else return true;
    }
    
    void dfs(int x, int y){
        if(tr[x][y] == '@'){
            cnt = 1;
            vis[x][y] = 1;
        }
        for(int i = 0; i < 8; ++i){
            int xx = x + dx[i];
            int yy = y + dy[i];
            if(!judge(xx, yy))continue;
            //vis[xx][yy] = 1;
            //cnt = 1;
            dfs(xx, yy);
            //vis[xx][yy] = 0;
        }
    }
    
    int main(){
        while (cin>>n>>m && (n + m)) {
            init();
            for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
            scanf(" %c", &tr[i][j]);
            for(int i = 1; i <= n; ++i)//直接暴力搜图
            for(int j = 1; j <= m; ++j){
                if(!vis[i][j] && tr[i][j] == '@'){
                    cnt = 0;
                    dfs(i, j);
                    if(cnt)ans++;
                }
            }
            cout<<ans<<endl;
        }
      	return 0;
    }
    

    思路2:

    这个题每个点只需要走一次,所以也可以用bfs,思路和dfs差不多

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    char tr[105][105];
    bool vis[105][105];
    int n, m, ans, cnt;
    int dx[] = {1, 0, -1, 0, -1, 1, 1, -1};
    int dy[] = {0, 1, 0, -1, -1, 1, -1, 1};
    struct ran{
        int x, y;
    };
    queue<ran>q;
    
    void init(){//初始化
        memset(vis, 0, sizeof(vis));
        memset(tr, 0, sizeof(tr));
        ans = 0;
    }
    
    bool judge(int x, int y){//判断条件
        if(x > n || x < 1 || y > m || y < 1)return false;
        else if(vis[x][y])return false;
        else if(tr[x][y] == '*')return false;
        else return true;
    }
    
    
    void bfs(int x, int y){
        if(tr[x][y] == '@' && vis[x][y] == 0){//更新答案
            cnt = 1;
        }
        while (!q.empty()) {//清空队列!!!
            q.pop();
        }
        ran now, next;
        now.x = x; now.y = y;
        q.push(now);
        vis[x][y] = 1;
        while (!q.empty()) {
            now = q.front();q.pop();
            for(int i = 0; i < 8; ++i){
                next.x = now.x + dx[i];
                next.y = now.y + dy[i];
                if(!judge(next.x, next.y))continue;
                q.push(next);
                vis[next.x][next.y] = 1;
            }
        }
    }
    
    int main(){
        while (cin>>n>>m && (n + m)) {
            init();
            for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
            scanf(" %c",&tr[i][j]);
            for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j){
                if(!vis[i][j] && tr[i][j] == '@'){
                    cnt = 0;
                    bfs(i, j);
                    if(cnt)ans++;
                }
            }
            cout<<ans<<endl;
        }
    }
    

    L - 变形课

    题意:

    给你一堆字符串,问你能不能按成语接龙的方式从b连到m

    思路:

    对dfs的灵活运用

    这个题有不止一个b开头的,如果暴力的话就得循环找每个b开头的,再去暴力,所以我们dfs也得这样,再者我们需要用两个数组,一个存字符串开头的字符,一个存字符串最后一个字符,dfs去跑搜的字符串的位置

    注意答案输出的时候还tm有个句号,艹

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <stdlib.h>
    #include <sstream>
    #include <map>
    #include <set>
    using  namespace std;
    #define inf 0x3f3f3f3f
    #define MAX 1000000 + 7
    #define endl '
    '
    #define mod 1e9+7;
    typedef  long long ll ;
    //不开longlong见祖宗!
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    
    inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;
            ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
    
    char star[MAX], end1[MAX];
    bool vis[MAX];
    string s;
    int n, ans;
    
    void dfs(int k){
        if(ans == 1){//找到答案就返回
            return;
        }
        if(end1[k] == 'm'){//找到了m
            ans = 1;
            return;
        }
        for(int i = 1; i <= n; ++i){
            if(vis[i])continue;
            if(star[i] == end1[k]){//判断能不能接龙成功
                vis[i] = 1;
                dfs(i);
                vis[i] = 0;
            }
        }
    }
    
    
    void init(){//初始化很重要
        memset(vis, 0, sizeof(vis));
        memset(star, 0, sizeof(star));
        memset(end1, 0, sizeof(star));
        ans = 0;n = 0;
    }
    
    int main(){
        while (cin>>s) {
            if(s [0] != '0'){//判断输入的是不是0
                star[++n] = s[0];
                end1[n] = s[s.size() - 1];
            }
            else if(s[0] == '0'){//是0就开始搜索
                for(int i = 1; i <= n; ++i){
                    if(star[i] == 'b'){
                        dfs(i);
                    }
                    if(ans == 1){//如果ans=1就直接跳出就可以了,没必要一直搜了
                        break;
                    }
                }
                if(ans)cout<<"Yes.
    ";
                else cout<<"No.
    ";
                init();//搜完记得初始化,以便下次再搜
            }
        }
        return 0;
    }
    

    写在最后:

    这份搜索题是20年十一月初的,一不小心鸽了四个月⁄(⁄ ⁄ ⁄ω⁄ ⁄ ⁄)⁄,深感愧疚,之前对搜索很抵触,不过上次牛客比赛遇到了个搜索题,写个dfs却wa了好多次才过,最后才发现是retuen后vis忘归0了,就感觉再不练练的话就说不过去了,现在补上了,总体来说对那种板子题还是能写的过去,不过要是换个题型就不太行了(╥﹏╥)。噢对了,还有两个英文题太懒的搞了,就没搞,请call me 小懒猪(*≧ω≦)

    不是所有的牛奶都叫特仑苏,也不是所有的人都叫猪猪
  • 相关阅读:
    决策树简介
    机器学习一百天-day7/11-KNN
    机器学习100天-day4,5,6,8逻辑回归
    机器学习一百天-day3多元线性回归及虚拟变量陷阱分析
    机器学习100天-day2简单线性回归
    机器学习100天-day1数据预处理
    sklearn.preprocessing.Imputer
    vue echart 中国地图 疫情图
    一周笔记
    js基础操作与方法
  • 原文地址:https://www.cnblogs.com/chelsea0901/p/14468019.html
Copyright © 2020-2023  润新知