NOJ的几道经典搜索题题解

来源:互联网 发布:匹配声音软件是什么 编辑:程序博客网 时间:2024/05/06 21:08

因为周六举行月赛,写几个经典的BFS DFS供大家参考,代码是以前写的不是很简洁,有不懂的可留言。

注:写搜索时一定要记得访问标记,以免访问过的点再次访问,出现死循环等情况。


1、走不出的迷宫:http://acm.nuc.edu.cn/OJ/problem.php?pid=1010

数据范围比较小,可以用递归,代码简洁些;

#include "stdio.h"
#define M 82
int dx[] = {0,1,0,-1}; //方向数组
int dy[] = {1,0,-1,0};
int DFS (int x,int y);
int n;
char map[M][M];
int DFS (int x,int y)
{
    inti,X,Y,flag;
    if (x ==n&& y== n)//找到出口,返回1
    {
       map[x][y] = '#'; //标记路径
       return 1;
    }
    if(map[x][y] == '1')
       return 0;
    map[x][y] ='*';//访问标记 以免重复访问
    flag =0;
    for (i = 0;i < 4; i ++)
    {
       X = x + dx[i];//查找四个方向
       Y = y + dy[i];
       if (map[X][Y] == '1'||map[X][Y] == '*') //该点不可走,或已访问过
           continue;
       else if (DFS(X,Y) == 1) flag = 1;
    }
    if (flag ==0)  //回退输出路径
       map[x][y] = '0';
    else
       map[x][y] = '#';
    returnflag;
}

int main ()
{
    inti,j,x,y;
    scanf ("%d%d %d",&n,&y,&x);
    for (i = 1;i <= n; i ++)
       for (j = 1; j <= n; j ++)
       {
           getchar ();
           scanf ("%c",&map[i][j]);
       }

    for (i = 0;i <=n+1; i ++) //给图加个框,就不必再判断点是否出界
       for (j = 0; j<=n+1; j ++)
           if (j == 0||i==0||j==n+1||i==n+1)
               map[i][j] = '1';
    if (DFS(x,y)== 1)
    {
       printf ("Found\n");
       for (i = 1; i <= n; i ++)
       {
           for (j =1; j <= n; j++)
           {
               if (j == n)
                   printf ("%c",map[i][j]);
               else
                   printf ("%c ",map[i][j]);
           }
           printf ("\n");
       }
    }
    else
       printf ("Not Found\n");
    return0;
}

2、Prison Break http://acm.nuc.edu.cn/OJ/problem.php?pid=1838

数据范围比较大,用递归用会RE,所以自己写栈或队列,这里用BFS做

#include "stdio.h"
#include "string.h"
#define M 1050

int dx[] = {-1,0,1,0};
int dy[] = {0,-1,0,1};
//int dir[4][2] = {{-1,0},{0,-1},{1,0},{0,1}}; 也可以这样写
int flow;
struct back
{
    intx0,y0;
    int n;//记录某点的前驱 记录路径用的

} b[M*M];
char map[M][M];
int BFS (int X,int Y,int m,int n)
{
    int front =0,num = 0;
    int rear =0;
    b[0].x0 =X;
    b[0].y0 =Y;
    while (front!= rear)
    {
       flow = front;
       X = b[front].x0;//从队列中取出点
       Y = b[front].y0;
       map[X][Y] = '*';//访问标记
       front ++;
       for (int i = 0; i < 4; i ++)//4个方向搜索
       {
           int x = X + dx[i];
           int y = Y + dy[i];
           if (x < 1|| y < 1||x>m||y>n) //找到出口,返回1
               return 1;
           else if (map[x][y] == '.') //可以走,进队列
           {
               rear ++;
               b[rear].x0 = x;
               b[rear].y0 = y;
               b[rear].n = front;
               map[x][y] = '*';
           }
       }
    }
    return0;
}

int main ()
{
    inti,j,k,m,n,x,y,t;
    longcount;
    charstr[M];
    while (scanf("%d %d",&m,&n))
    {
       if (m==0&&n==0)
           break;
       getchar ();
       count = 1;
       for (i = 1; i <= m; i ++)//读入地图
       {
           k = 0;
           j = 1;
           gets (str);
           while (str[k] != '\0')
           {
               map[i][j] = str[k++];
               if (map[i][j] == 'X')
               {
                   x = i;
                   y = j;
               }
               j ++;
           }
           memset (str,'\0',sizeof (str));
       }
       if (BFS (x,y,m,n))
       {
           map[x][y] = 'X';
           while (1) //输出路径
           {
               if (b[flow].x0==x&&b[flow].y0==y)
                   break;
               map[b[flow].x0][b[flow].y0] = 'w';
               flow = b[flow].n;
               count ++; //记录步数
           }
           printf ("You can escaped in %ld minute(s).\n",count);
           for (i = 1; i <= m; i ++)
           {
               for (j = 1; j <= n; j ++)
               {
                   if (map[i][j] == '*')
                       printf (".");
                   else
                       printf ("%c",map[i][j]);
               }
               printf ("\n");
           }
           printf ("\n");
       }
       else
           printf ("My good friend, may God bless you!\n\n");
       memset (map,'\0',sizeof(map));
    }
    return0;
}

3、图像审查 http://acm.nuc.edu.cn/OJ/problem.php?pid=1060

这题是BFS与DFS结合,也得自己写栈,否则会超时,这里用到一个就 floodfill算法,这里不多说,百度之;其实就是BFS。

#include "stdio.h"
#define M 1005
char map[M][M];
int dx0[] = {-1,0,1,0};
int dy0[] = {0,-1,0,1};
int dx[] = {-1,-1,0,1,1,1,0,-1};
int dy[] = {0,-1,-1,-1,0,1,1,1};
struct node
{
    intx,y;
} visit[1000000],find[1000000];
void BFS(int x,int y,int n,int m)
{
    intfront,rear,i,x0,y0;
    front = rear= 0;
   find[++rear].x = x;
    find[rear].y= y;
    while (front!= rear)
    {
       x0 = find[front].x;
       y0 = find[front++].y;
       if (map[x0][y0] == '0')//把原来是‘0’的地方变为‘#’
           map[x0][y0] = '#';
       for (i = 0; i < 4; i ++)
       {
           x = x0+dx0[i];
           y = y0+dy0[i];
           if (x<0||x>=n||y<0||y>=m)
               continue;
           if (map[x][y] == '1')
           {
               map[x][y] = '2';//1 变为 2
               continue;
           }
           if (map[x][y] == '0')
           {
               map[x][y] = '#';
               find[++rear].x = x;
               find[rear].y = y;
           }
       }
    }
}
void DFS (int x,int y,int n,int m)//DFS 查找有多少个用2组成的图形
{
    inti,x0,y0;
    int top =0;
    visit[top].x= x;
   visit[top++].y = y;
    while (top>= 0)
    {

       x0 = visit[--top].x;
       y0 = visit[top].y;
       map[x0][y0] = '*';
       for (i = 0; i < 8; i ++)
       {
           x = x0+dx[i];
           y = y0+dy[i];
           if (x > 0&&x < n&&y>0&&y
           {
               visit[top].x = x;
               visit[top++].y = y;
           }
       }
    }
}

int main ()
{
    intn,m,n0,m0,i,j,count = 0;
    scanf ("%d%d",&n0,&m0);
    n =n0+2;
    m =m0+2;
    getchar();
    for (i = 1;i <= n0; i ++)
       gets (map[i]+1);

    for (i = 0;i <= n0+1; i ++)
       for (j = 0; j <= m0+1; j ++)
           if (i==0||i==n0+1||j==0||j==m0+1)//加框,以原图外一点为起点 (自己想想为什么)
               map[i][j] = '0';
   BFS(0,0,n,m);//bfs 进行涂色
    for (i = 0;i < n; i ++)
       for (j = 0; j < m; j ++)
           if (map[i][j] == '2')//找出有多少个图形
           {
               count ++;
               DFS (i,j,n,m);
           }
    printf("There are %d shape elements\n",count);
    return0;
}


原创粉丝点击