BFS/DFS

来源:互联网 发布:海阔天空 信乐团知乎 编辑:程序博客网 时间:2024/06/03 05:06

 #include<cstdio>  

 #include<cstring>  

#include<cstdlib>  

 using namespace std;  

const int maxn=100;  

 bool biaoji[maxn][maxn]; // 访问标记  

int map[maxn][maxn]; // 坐标范围  

 int dir[4][2]={0,1,0,-1,1,0,-1,0}; // 方向向量,(x,y)周围的四个方向  

   

bool CheckEdge(int x,int y) // 边界条件和约束条件的判断  

 {  

     if(!biaoji[x][y] && ...) // 满足条件  

        return 1;  

     else // 与约束条件冲突  

         return 0;  

 }  

  

 void dfs(int x,int y)  

 {  

     biaoji[x][y]=1; // 标记该节点被访问过  

     if(map[x][y]==G) // 出现目标态G  

         {  

         ...... // 做相应处理  

         return;  

         }  

     for(int i=0;i<4;i++)  

     {  

        if(CheckEdge(x+dir[i][0],y+dir[i][1])) // 按照规则生成下一个节点  

             dfs(x+dir[i][0],y+dir[i][1]);  

     }  

     return// 没有下层搜索节点,回溯  

 }  

 int main()  

 {  

 return 0;  


例如杭电1242:

题目大意是,从起点走到目标点去,并且花的时间最少   

#include<cstdio>

#include<cstring>

#include<iostream>

 

using namespace std;

#define max 205

 

char map[max][max];

long a[100000],step,sum,n,m,visited[max][max];

long directions[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

 

void DFS(int x,int y)

{

    if(map[x][y] == 'r') a[sum++] = step;

    else if(map[x][y] != '#')

    {

          for(int i = 0; i < 4; i++)

          {

                int tx, ty;

                tx = x + directions[i][0];

                ty = y + directions[i][1];

                if( map[tx][ty] != '#' && tx>=1 && tx <= n && ty >= 1 && ty <= m && visited[tx][ty] == 0)

                {

                      if(map[tx][ty] == 'x')

                      {

                            step ++;

                      }

                      step++;

                      visited[tx][ty] = 1;

                      DFS(tx, ty);

                      visited[tx][ty] = 0;

                      step--;

                      if(map[tx][ty] == 'x')

                        step--;

                }

          }

    }

}

 

int main()

{

    long i,j,x,y,min;

    while(scanf("%ld%ld",&n,&m)>0)

    {

        memset(visited,0,sizeof(visited));

        sum=0;

        step=0;

        min=max;

 

        for(i=1;i<=n;i++)

        {

            getchar();

            for(j=1;j<=m;j++)

            {

                scanf("%c",&map[i][j]);

                if(map[i][j]=='a')

                {

                    x=i;

                    y=j;

                }

            }

        }

        visited[x][y]=1;

        DFS(x,y);

        if(sum==0)

            printf("Poor ANGEL has to stay in the prison all his life.\n");

        else

        {

            for(i=0;i<sum;i++)

                if(a[i]<min)

                    min=a[i];

            printf("%ld\n",min);

        }

    }

    return 0;

}



  广度优先搜索 

 * @param Vs 起点 

  * @param Vd 终点 

  */  

 bool BFS(Node& Vs, Node& Vd){  

     queue<Node> Q;  

    Node Vn, Vw;  

    int i;  

   

     //初始状态将起点放进队列Q  

     Q.push(Vs);  

     hash(Vw) = true;//设置节点已经访问过了!  

   

     while (!Q.empty()){//队列不为空,继续搜索!  

        //取出队列的头Vn  

         Vn = Q.front();  

   

         //从队列中移除  

         Q.pop();  

   

        while(Vw = Vn通过某规则能够到达的节点){  

             if (Vw == Vd){//找到终点了!  

                 //把路径记录,这里没给出解法  

                 return true;//返回  

             }  

   

             if (isValid(Vw) && !visit[Vw]){  

                 //Vw是一个合法的节点并且为白色节点  

                 Q.push(Vw);//加入队列Q  

                 hash(Vw) = true;//设置节点颜色  

             }  

         }  

     }  

     return false;//无解  

}


例如杭电1242:

题目大意是,从起点走到目标点去,并且花的时间最少

 #include <cstdio>

#include <cstring>

#include <cmath>

#include <set>  

#include <map>

#include <queue>

#include <string>

#include <iostream>

#include <algorithm>

#define INF 100000

using namespace std;

int sx, sy, ex, ey, n, m;

char mp[1000][1000];

int visit[1000][1000];   //用来标记是否走过(0为没有走过     1为走过了)

int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };

struct node    //结构体

{

int x, y;

int step;

};

int f(int x,int y)   //判断是否能走

{

if (x >= 0 &&x < n && y >= 0 && y < m && mp[x][y] !='#' && visit[x][y] == 0)return 1;

return 0;

}

int bfs()

{

memset(visit, 0, sizeof(visit));   //全部的点都设为未标记

queue<node> que;

node frist, second;    //frist用来表示当前位置的点,  second用来表示下一位置的点

frist.x = sx, frist.y = sy, frist.step = 0;   //初始化,起点位置,步数设为0

visit[sx][sy] = 1;       //把该点标记

que.push(frist);        //把第一个点压入

while (!que.empty())

{

frist = que.front(); que.pop();

int x = frist.x, y = frist.y;

if (x == ex && y == ey) return frist.step;   //到达目标位置时结束

for (int i = 0; i < 4; i++)

{

int xx = x + dx[i], yy = y + dy[i];

if (f(xx, yy))

{

second.x = xx, second.y = yy;

second.step = frist.step + 1;

if (mp[xx][yy] == 'x') second.step++;  //题目要求特殊处理

que.push(second);

visit[xx][yy] = 1;

}

}

}

return -1;

}

int main()

{

while (scanf("%d%d", &n, &m) !=EOF)

{

for (int i = 0; i < n; i++)

{

for (int j = 0; j < m; j++)

{

cin >> mp[i][j];

if (mp[i][j] == 'r') { sx = i; sy = j; }

if (mp[i][j] == 'a') { ex = i; ey = j; }

}

}

int ans = bfs();

if (ans == -1) printf("Poor ANGEL has to stay in the prison all his life.\n");

else printf("%d\n", ans);

}

return 0;

}

 

杭电2612  题目大意:两个人要到一个东西(这个东西可能有多个)的最短距离。

 

#include <cstdio>

#include <cstring>

#include <cmath>

#include <set>  

#include <map>

#include <queue>

#include <string>

#include <iostream>

#include <algorithm>

#define INF 100000

using namespace std;

int sx, sy, ex, ey, n, m;

char mp[1000][1000];

int visit[1000][1000];   //用来标记是否走过(0为没有走过     1为走过了)

int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };

int a[2][205][205];    //用来表示从起点到任一点的距离

int yx, yy, mx, my;

struct node    //结构体

{

int x, y;

int step;

};

int f(int x,int y)   //判断是否能走

{

if (x >= 0 &&x < n && y >= 0 && y < m && mp[x][y] !='#' && visit[x][y] == 0)return 1;

return 0;

}

void bfs(int sx,int sy,int k)

{

memset(visit, 0, sizeof(visit));   //全部的点都设为未标记

for (int i = 0; i < n; i++)

{

for (int j = 0; j < m; j++)

{

a[k][i][j] = INF;

}

}

queue<node> que;

node frist, second;    //frist用来表示当前位置的点,  second用来表示下一位置的点

frist.x = sx, frist.y = sy, frist.step = 0;   //初始化,起点位置,步数设为0

a[k][sx][sy] = 0;   //用来表示从起点到任一点的距离

visit[sx][sy] = 1;       //把该点标记

que.push(frist);        //把第一个点压入

while (!que.empty())

{

frist = que.front();

que.pop();

int x = frist.x, y = frist.y;  //x、y分别是当前位置的横纵坐标

for (int i = 0; i < 4; i++)

{

int xx = x + dx[i], yy = y + dy[i];

if (f(xx, yy))

{

second.x = xx, second.y = yy;

a[k][xx][yy] = a[k][x][y] + 1;

visit[xx][yy] = 1;

que.push(second);

}

}

}

}

int main()

{

while (scanf("%d%d", &n, &m) !=EOF)

{

for (int i = 0; i < n; i++)

{

for (int j = 0; j < m; j++)

{

cin >> mp[i][j];

if (mp[i][j] == 'Y') { yx = i; yy = j; }

if (mp[i][j] == 'M') { mx = i; my = j; }

}

}

bfs(yx, yy, 0);

bfs(mx, my, 1);

int minn = INF;

for (int i = 0; i < n; i++)

{

for (int j = 0; j < m; j++)

{

if (mp[i][j] == '@')

{

minn = min(minn, a[0][i][j] + a[1][i][j]);

}

}

}

minn = minn * 11;

cout << minn << endl;

}

return 0;

}



原创粉丝点击