六战HDU1241 Oil Deposits 对搜索的不断反思

作者分享了自己在算法竞赛中遇到的问题与解决过程,包括了对代码逻辑的理解、边界条件的检查、以及如何避免常见错误。通过一系列实例,详细解释了如何使用BFS和DFS解决迷宫探索问题,并逐步优化代码,最终实现高效解决问题的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一战:


结果: PKU 顺利AC  HDU 死都是 WA  这就郁闷了。。。


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

using namespace std;

typedef struct node
{
    int x;
    int y;
}node;

void BFS(int i,int j,char map[][100+10],int visited[][100+10])
{
    node xx;
    xx.x = i;
    xx.y = j;
    queue<node>q;
    q.push(xx);

    while(!q.empty())
    {
        node now;
        now = q.front();
        q.pop();

//        if( (map[now.x-1][now.y]=='@' && !visited[now.x-1][now.y]) ||
//            (map[now.x+1][now.y]=='@' && !visited[now.x+1][now.y]) ||
//            (map[now.x][now.y-1]=='@' && !visited[now.x][now.y-1]) ||
//            (map[now.x][now.y+1]=='@' && !visited[now.x][now.y+1]) ||
//
//            (map[now.x+1][now.y+1]=='@' && !visited[now.x+1][now.y+1]) ||
//            (map[now.x-1][now.y+1]=='@' && !visited[now.x-1][now.y+1]) ||
//            (map[now.x+1][now.y-1]=='@' && !visited[now.x+1][now.y-1]) ||
//            (map[now.x-1][now.y-1]=='@' && !visited[now.x-1][now.y-1])
//
//
//           )
//        {
//            q.push(now);
//            visited[now.x][now.y]=1;
//        }

    if( (map[now.x-1][now.y]=='@' && !visited[now.x-1][now.y]) )
    {
            node last;
            last.x = now.x-1;
            last.y = now.y;

            q.push(last);
            visited[last.x][last.y]=1;
    }

    if( (map[now.x+1][now.y]=='@' && !visited[now.x+1][now.y]) )
    {

            node last;
            last.x = now.x+1;
            last.y = now.y;
            q.push(last);
            visited[last.x][last.y]=1;
    }

    if( (map[now.x][now.y-1]=='@' && !visited[now.x][now.y-1]) )
    {
            node last;
            last.x = now.x;
            last.y = now.y-1;

            q.push(last);
            visited[last.x][last.y]=1;
    }

    if( (map[now.x][now.y+1]=='@' && !visited[now.x][now.y+1]) )
    {
            node last;
            last.x = now.x;
            last.y = now.y+1;

            q.push(last);
            visited[last.x][last.y]=1;
    }

    if( (map[now.x+1][now.y+1]=='@' && !visited[now.x+1][now.y+1]) )
    {
            node last;
            last.x = now.x+1;
            last.y = now.y+1;

            q.push(last);
            visited[last.x][last.y]=1;
    }

    if( (map[now.x-1][now.y+1]=='@' && !visited[now.x-1][now.y+1]) )
    {
            node last;
            last.x = now.x-1;
            last.y = now.y+1;

            q.push(last);
            visited[last.x][last.y]=1;
    }

    if( (map[now.x+1][now.y-1]=='@' && !visited[now.x+1][now.y-1]) )
    {
            node last;
            last.x = now.x+1;
            last.y = now.y-1;

            q.push(last);
            visited[last.x][last.y]=1;
    }

    if( (map[now.x-1][now.y-1]=='@' && !visited[now.x-1][now.y-1]) )
    {
            node last;
            last.x = now.x-1;
            last.y = now.y-1;

            q.push(last);
            visited[last.x][last.y]=1;
    }










    }


}

int main()
{
    int m,n;
    while(~scanf("%d%d",&m,&n))
    {
        char map[100+10][100+10];
        int visited[100+10][100+10]={0};
        for(int i=0;i<m;i++)
            scanf("%s",map[i]);

        int cnt = 0;

        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
            {
                if(map[i][j]=='@' && !visited[i][j])
                {
                    BFS(i,j,map,visited);
                    cnt++;
                }
            }
        cout<<cnt<<"\n";

    }
    return 0;
}

PKU 过了,说明这么久没打了,大方向还是没出什么问题。。现在就是找错了。。找错找的都哭了。。


1. 第一个进去的visited 没有标记访问。(我++  ,我一直以为我写了的啊。。。)

2.  没有对 now.x-1 >=0 和 now.x+1 < m  的检查。 (这个我承认是真的错误了,因为我是想着,当不合条件以后,map 就不可能为 @ 了,所以就没有专门检查      后来知道这个可是大错啊 !!!  HDU 就是挂的这里,数组越界了,但是存的运气不好还是原来的值。。。这样就错了,内存当中取得还是原来的值、、、PKU 可能运行的时候刚好没碰到的这样的取到恰好 '@' 的值)


第二战: 

又跪了。。。致命错误,就不放代码了。。大致一样

不能有等于号啊!!!   now.x -1 >=0 是没错 但是now.x+1 写的是<=m   等于m 就出界了。。。。


第三战:

上面的代码长的吓人。。。8个方向,分8个if 来写了  第三战给出用数组标识方向,用循环来改变方向


#include<iostream>
#include<cstdio>
#include<queue>

using namespace std;

typedef struct node
{
    int x;
    int y;
}node;

void BFS(int xx,int yy,char map[][100+10],char visited[][100+10],int m,int n,int xi[],int yi[])
{
    queue<node>q;
    node a;
    a.x = xx;
    a.y = yy;
    q.push(a);
    visited[a.x][a.y] = 1;
    while(!q.empty())
    {
        node now = q.front();
        q.pop();

        for(int i=0;i<8;i++)
        {
            node now2;
            now2.x = now.x + xi[i];
            now2.y = now.y + yi[i];
            if(now2.x>=0 && now2.x <m && now2.y >=0 && now2.y<n && !visited[now2.x][now2.y] && map[now2.x][now2.y]=='@')
            {
                q.push(now2);
                visited[now2.x][now2.y] = 1;
            }

        }
    }

}


int main()
{
    int m,n;
    while(~scanf("%d%d",&m,&n) && m != 0)
    {
        char map[100+10][100+10];
        char visited[100+10][100+10] = {0};
        for(int i=0;i<m;i++)
            scanf("%s",map[i]);

        int xi[] = {-1,  0,  1,  1,  1, 0,  -1, -1};
        int yi[] = {-1, -1, -1,  0,  1, 1,   1,  0};

        int cnt = 0;

        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
        {
            if(map[i][j]=='@' && !visited[i][j])
            {
                BFS(i,j,map,visited,m,n,xi,yi);
                cnt++;
            }
        }
        cout<<cnt<<endl;
    }
    return 0;
}



第四战:  命名太操蛋。。。重新来,标准一下名字


#include<iostream>
#include <queue>
#include <cstdio>

using namespace std;

typedef struct
{
    int x;
    int y;
}node[100+10];                         // 用数组的话 就直接结构体数组啊

void BFS(int xx,int yy,char map[][100+10],bool visited[][100+10],int x_i[],int y_i[],int M,int N)
{
    queue<node>q;
    node a;
    a.x = xx;
    a.y = yy;
    q.push(a);
    visited[xx][yy] = true;
    while(!q.empty())
    {
        node get_new = q.front();
        q.pop();
         判断是否满足条件
        for(int i=0;i<8;i++)
            {
                int nx = get_new.x + x_i[i];
                int ny = get_new.y + y_i[i];

                if(nx>=0 && nx<M && ny>=0 && ny<N && map[nx][ny]=='@' && !visited[nx][ny])
                {
                    node inside;
                    inside.x = nx;
                    inside.y = ny;
                    q.push(inside);
                    visited[nx][ny] = true;
                }

            }

    }
    return;
}

int main()
{
    int M,N;
    while(cin>>M>>N && M !=0)
    {
        char map[100+10][100+10];               // 省略 visited 数组  标记数组  省去不好  省去就是改变了原来的图,文本的状态,一个题目可以  但是真实搜索的话  不止是一个图 还是不能省略记忆数组
        bool visited[100+10][100+10] = {false};

        for(int i=0;i<M;i++)
            cin>>map[i];               // 可以 cin 就不用 scanf 了

        int cnt=0;

        int x_i[] = {-1,  0,  1,  1,  1, 0,  -1, -1};
        int y_i[] = {-1, -1, -1,  0,  1, 1,   1,  0};

        for(int i=0;i<M;i++)
            for(int j=0;j<N;j++)
            {
                if(map[i][j]=='@' && !visited[i][j])
                {
                    BFS(i, j, map, visited, x_i, y_i, M, N);
                    cnt++;
                }
            }
        cout<<cnt<<endl;

    }
    return 0;
}


第五战:   丢掉STL   数组模拟队列


#include<iostream>

#include <cstdio>

using namespace std;

typedef struct
{
    int x;
    int y;
}nodexx;                         // 用数组的话 就直接结构体数组啊

void BFS(int xx,int yy,char map[][100+10],bool visited[][100+10],int x_i[],int y_i[],int M,int N)
{

    nodexx node[100000+10];   // 开100 根本过不了 1000 都不行  10W 才过
    int front=-1,rear=-1;
    node[++rear].x = xx;
    node[rear].y = yy;
    visited[xx][yy] = true;

    while(rear > front)
    {
        int get_x = node[++front].x;
        int get_y = node[front].y;

        for(int i=0;i<8;i++)
        {
            int nx = get_x + x_i[i];
            int ny = get_y + y_i[i];

            if(nx>=0 && nx<M && ny>=0 && ny<N && map[nx][ny]=='@' && !visited[nx][ny])
            {
                node[++rear].x = nx;
                node[rear].y   = ny;
                visited[nx][ny] = true;
            }
        }
    }
    return;
}

int main()
{
    int M,N;
    while(cin>>M>>N && M !=0)
    {
        char map[100+10][100+10];               // 省略 visited 数组  标记数组  省去不好  省去就是改变了原来的图,文本的状态,一个题目可以  但是真实搜索的话  不止是一个图 还是不能省略记忆数组
        bool visited[100+10][100+10] = {false};

        for(int i=0;i<M;i++)
            cin>>map[i];               // 可以 cin 就不用 scanf 了

        int cnt=0;

        int x_i[] = {-1,  0,  1,  1,  1, 0,  -1, -1};
        int y_i[] = {-1, -1, -1,  0,  1, 1,   1,  0};

        for(int i=0;i<M;i++)
            for(int j=0;j<N;j++)
            {
                if(map[i][j]=='@' && !visited[i][j])
                {
                    BFS(i, j, map, visited, x_i, y_i, M, N);
                    cnt++;
                }
            }
        cout<<cnt<<endl;
    }
    return 0;
}


第六战:换成 DFS 继续来做  修改BFS 函数,一次性过



#include<iostream>

#include <cstdio>

using namespace std;

void DFS(int xx,int yy,char map[][100+10],bool visited[][100+10],int x_i[],int y_i[],int M,int N)
{
    visited[xx][yy] = true;
    for(int i=0;i<8;i++)
    {
        int nx = xx + x_i[i];
        int ny = yy + y_i[i];

        if(nx>=0 && nx<M && ny >=0 && ny<N && map[nx][ny]=='@' && !visited[nx][ny])
        {
            DFS(nx,ny,map,visited,x_i,y_i,M,N);
        }
    }
}

int main()
{
    int M,N;
    while(cin>>M>>N && M !=0)
    {
        char map[100+10][100+10];               // 省略 visited 数组  标记数组  省去不好  省去就是改变了原来的图,文本的状态,一个题目可以  但是真实搜索的话  不止是一个图 还是不能省略记忆数组
        bool visited[100+10][100+10] = {false};

        for(int i=0;i<M;i++)
            cin>>map[i];               // 可以 cin 就不用 scanf 了

        int cnt=0;

        int x_i[] = {-1,  0,  1,  1,  1, 0,  -1, -1};
        int y_i[] = {-1, -1, -1,  0,  1, 1,   1,  0};

        for(int i=0;i<M;i++)
            for(int j=0;j<N;j++)
            {
                if(map[i][j]=='@' && !visited[i][j])
                {
                    DFS(i, j, map, visited, x_i, y_i, M, N);
                    cnt++;
                }
            }
        cout<<cnt<<endl;
    }
    return 0;
}


最后给出两个比较不错的代码,来自 http://blog.youkuaiyun.com/yueashuxia/article/details/7171585


BFS代码 代码:

#include<stdio.h>  
  
int m, n;  
char grid[105][105];  
int x[8] = {-1, -1, -1, 0, 1, 1, 1, 0};  
int y[8] = {-1, 0, 1, 1, 1, 0, -1, -1};  
  
struct node  
{  
    int x, y;      
}Q[10005];  
  
void bfs(int a, int b)  
{  
    int top = 0, i, j, tx, ty;  
    Q[top].x = a;  
    Q[top++].y = b;  
    grid[a][b] = '*';  
    for(i = 0; i < top; i ++)  
    {  
        for(j = 0; j < 8; j ++)  
        {  
            tx = Q[i].x + x[j];  
            ty = Q[i].y + y[j];  
            if(tx >= 0 && ty >= 0 && tx < m && ty < n && grid[tx][ty] == '@')  
            {  
                grid[tx][ty] = '*';  
                Q[top].x = tx;  
                Q[top++].y = ty;    
            }      
        }      
    }  
}  
  
int main(){  
    int i, j, cnt;  
    while(scanf("%d%d", &m, &n), m)  
    {  
        for(i = cnt = 0; i < m; i ++)  
        {  
            scanf("%s", grid[i]);      
        }      
        for(i = 0; i < m; i ++)  
        {  
            for(j = 0; j < n; j ++)  
            {  
                if(grid[i][j] == '@')  
                {  
                    cnt++ ;  
                    bfs(i, j);      
                }         
            }      
        }  
        printf("%d\n", cnt);  
    }  
    return 0;  
}  

DFS 代码:

#include<stdio.h>  
  
int m, n;  
char grid[105][105];  
int x[8] = {-1, -1, -1, 0, 1, 1, 1, 0};  
int y[8] = {-1, 0, 1, 1, 1, 0, -1, -1};  
  
void dfs(int a, int b)  
{  
    int i, tx, ty;  
    grid[a][b] = '*';  
    for(i = 0; i < 8; i ++)  
    {  
        tx = a + x[i];  
        ty = b + y[i];      
        if(tx >= 0 && ty >= 0 && tx < m && ty < n && grid[tx][ty] == '@')  
        {  
            dfs(tx, ty);  
        }   
    }  
}  
  
int main()  
{  
    int i, j, cnt;  
    while(scanf("%d%d", &m, &n), m)  
    {  
        for(i = cnt = 0; i < m; i ++)  
        {  
            scanf("%s", grid[i]);      
        }      
        for(i = 0; i < m; i ++)  
        {  
            for(j = 0; j < n; j ++)  
            {  
                if(grid[i][j] == '@')  
                {  
                    cnt++ ;  
                    dfs(i, j);      
                }         
            }      
        }  
        printf("%d\n", cnt);  
    }  
    return 0;  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值