搜索 (bfs,dfs) 总结

A - A
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu

Description

  话说 CZ 由于不守基道,被妖怪抓走了,好基友 WP 在努力讨好高富帅 RQ 救出 CZ 的同时, CZ 也意识到了自己的错误,然后努力的想逃出妖怪的闺房。 

Input

 每组测试数据的第一行有三个整数   n,m,t(2<=n,m<=20,t>0)。接下来的   n行   m列为闺房的地图,其中包括   :
代表路
代表墙
代表CZ的起始位置
代表闺房的出口
A-J 代表带锁的门,对应的钥匙分别为a-j
a-j 代表钥匙,对应的门分别为A-J

每组测试数据之间有一个空行。

Output

 针对每组测试数据,如果可以成功逃亡,请输出最少需要多少分钟才能离开,如果不能则输出   -1

Sample Input

4 5 17
@A.B.
a*.*.
*..*^
c..b*

4 5 16
@A.B.
a*.*.
*..*^
c..b*

Sample Output

16
-1

 思路如下:

用进制转换的方法标记第三维,也就是钥匙的状态,

当前状态的钥匙存储状态,无法保证同一时刻正在进行的另一状态,

有无钥匙,所以说必须是三维数组,同时存储当前第三维所有 该钥匙位置的状态

代码如下:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;

const int INF = 1<<10;//将1左移十位
const int N = 22;
const int Size = 999999;
char map[N][N] ;
int vis[N][N][INF];//三维表示状态
struct node
{
    int x,y,z,ans ;
}q[Size];//结构体成员变量

int n,m,T;
int mv[4][2] = {{1,0},{0,-1},{-1,0},{0,1}};//定义一个移动数组

void BFS(int x ,int y)
{
    int s = 0 , e = 0  ;
    node f , t ;
    t.x = x ;
    t.y = y ;
    t.ans = 0 ;
    t.z = 0 ;
    q[e++] = t ;
    vis[t.x][t.y][t.z] = 1;
    while(s < e)
    {
        t = q[s++] ;
        if(map[t.x][t.y]=='^' && t.ans < T)//表示找到出口,直接输出步数,返回结果即可
        {
                printf("%d\n", t.ans);
                return ;
        }
        for(int i = 0;i < 4;i++)//否则循环4个方向进行搜索
        {
            f.x = t.x + mv[i][0];
            f.y = t.y + mv[i][1];
			f.z = t.z;
            if(f.x >= 0 && f.x < n && f.y >= 0 && f.y < m && vis[f.x][f.y][f.z]==0)
            {
                if(map[f.x][f.y]=='@' || map[f.x][f.y]=='.' || map[f.x][f.y]=='^')
                {
                    f.ans = t.ans  + 1;
                    q[e++] = f ;
                    vis[f.x][f.y][f.z] = 1 ;
                }
                else if('a' <= map[f.x][f.y] && map[f.x][f.y] <='j' )
                {
                    int sum = 0,kk,xx;
                    f.ans  = t.ans  + 1;
                    xx = f.z;
                    kk = map[f.x][f.y] - 'a' + 1;
                    for(int ll = 0;ll<kk;ll++)
                    {
                        sum = xx % 2;
                        xx /= 2;
                    }
                    if(sum==0)
                        f.z += pow(2,(map[f.x][f.y]-'a'));

                     vis[f.x][f.y][f.z] = 1 ;
                    q[e++] = f ;
                }
                else if('A' <= map[f.x][f.y] && map[f.x][f.y] <='J' )
                {
                    int sum = 0,kk,xx;
                    f.ans  = t.ans  + 1;
                    xx = f.z;
                    kk = map[f.x][f.y] - 'A' + 1;
                    for(int ll = 0;ll<kk;ll++)
                    {
                        sum = xx % 2;
                        xx /= 2;
                    }
                    if(sum==1)
                    {
                        f.ans  = t.ans  + 1;
                    q[e++] = f ;
                    vis[f.x][f.y][f.z] = 1 ;
                    }
                }
            }
        }
    }
    printf("-1\n");
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&T))
    {
            int x,y;
            memset(vis,0,sizeof(vis));//清空数组
            for(int i = 0 ; i < n ; i++)
            {
                scanf("%s%*c", map[i]);
            }
            for(int i = 0;i<n;i++)
            {
                 for(int j = 0;j < m;j++)
                {
                    if(map[i][j]=='@')
                    {
                        x = i;
                        y = j;
                        break;
                    }
                }
            }
       BFS(x,y);
    }
    return 0;
}
B - B
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu

 

Description

X,作为户外运动的忠实爱好者,总是不想呆在家里。现在,他想把死宅Y从家里拉出来。问从X的家到Y的家的最短时间是多少。

Input

多组输入。每组测试数据首先输入两个整数n,m(1<= n ,m<=15 )表示地图大小。接下来的n 行,每行n个字符。保证输入数据合法。

Output

若X可以到达Y的家,输出最少时间,否则输出 -1。

Sample Input

3 3
X#Y
***
#*#
3 3
X#Y
*#*
#*#

Sample Output

4
-1

Hint

思路如下:

分四个方向进行搜索,也可用bfs(广搜)或dfs(深搜)

代码如下:

   1.BFS

#include <stdio.h>
#include <string.h>

char Map[16][16];
int mv[16][16];

//mv[i][j] == 0 没有被访问
//mv[i][j] == 1 已经被访问

struct N
{
    int x,y,ans;
} q[300];

int jx[] = { 0,-1, 0, 1};
int jy[] = { 1, 0,-1, 0};

void bfs(int x,int y,int n,int m)
{
    int s = 0,e = 0;
    N t,f;

    t.x = x,t.y = y,t.ans = 0;

    q[e++] = t;

    mv[t.x][t.y] = 1;

    while(s < e)
    {
        t = q[s++];

//printf("x = %d,y = %d,ans = %d\n",t.x,t.y,t.ans);

        if(Map[t.x][t.y] == 'Y')
        {
            printf("%d\n",t.ans);
            return ;
        }

        for(int i = 0; i < 4; ++i)
        {
            f.x = t.x + jx[i];
            f.y = t.y + jy[i];

            if(0 <= f.x && f.x < n && 0 <= f.y && f.y < m && mv[f.x][f.y] == 0 && Map[f.x][f.y] != '#')
            {
                f.ans = t.ans+1;
                q[e++] = f;
                mv[f.x][f.y] = 1;
            }
        }
    }
    printf("-1\n");
    return ;
}

int main()
{
    int n,m,i,j;

    while(scanf("%d %d",&n,&m) != EOF)
    {
        memset(mv,0,sizeof(mv));

        for(i = 0; i < n; ++i)
        {
            scanf("%*c%s",Map[i]);
        }

        for(i = 0; i < n; ++i)
        {
            for(j = 0; j < m; ++j)
            {
                if(Map[i][j] == 'X')
                    break;
            }
            if(j != m)
                break;
        }

        bfs(i,j,n,m);
    }
    return 0;
}


  2.DFS

#include <stdio.h>
#include <string.h>

char Map[16][16];
int mv[16][16];

//mv[i][j] == 0 没有被访问
//mv[i][j] == 1 已经被访问

struct N
{
    int x,y,ans;
} q[300];

int jx[] = { 0,-1, 0, 1};
int jy[] = { 1, 0,-1, 0};

int Min;

void dfs(int x,int y,int n,int m,int ans)
{
    if(ans >= Min)
    {
        return ;
    }

    if(Map[x][y] == 'Y')
    {
        if(ans < Min)
        {
            Min = ans;
        }
        return ;
    }

    N f;

    for(int i = 0; i < 4; ++i)
    {
        f.x = x + jx[i];
        f.y = y + jy[i];

        if(0 <= f.x && f.x < n && 0 <= f.y && f.y < m && mv[f.x][f.y] == 0 && Map[f.x][f.y] != '#')
        {
            mv[f.x][f.y] = 1;
            dfs(f.x,f.y,n,m,ans+1);
            mv[f.x][f.y] = 0;
        }
    }
}

int main()
{
    int n,m,i,j;

    while(scanf("%d %d",&n,&m) != EOF)
    {
        memset(mv,0,sizeof(mv));

        for(i = 0; i < n; ++i)
        {
            scanf("%*c%s",Map[i]);
        }

        for(i = 0; i < n; ++i)
        {
            for(j = 0; j < m; ++j)
            {
                if(Map[i][j] == 'X')
                    break;
            }
            if(j != m)
                break;
        }

        Min = (1<<20);

        dfs(i,j,n,m,0);

        if(Min == (1<<20))
        {
            printf("-1\n");
        }
        else
        {
            printf("%d\n",Min);
        }

    }
    return 0;
}
C - C
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu

 

Description

You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:

Input

 On the first and only line are the numbers A, B, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).

Output

 The first line of the output must contain the length of the sequence of operations K.  If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.

Sample Input

3 5 4

Sample Output

6

Hint

思路如下:

题意:给出两个容积分别为 a 和 b 的pot,按照以下三种操作方式,求出能否在一定步数后,使者两个pot的其中一个的水量为c。

      1.FILL(i):将ipot倒满水。

      2.DROP(i):将ipot倒空水。

      3.POUR(i,j): 将ipot的水倒到jpot上,直至要么ipot为空,要么jpot为满。

 

思路:bfs求最短路径,与1426类似,只是每个节点的子节点数为6个而已。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int A, B, C;
int vis[105][105];
struct node
{
    int a, b, step;
};

void BFS()
{
    queue <node> q;
    int sa,sb;
    node f,t;
    f.a = 0; f.b = 0; f.step = 0;
    vis[f.a][f.b] = 1;
    q.push(f);
    while (!q.empty())
    {
        t = q.front();
        q.pop();
        if (t.a == C || t.b == C)
        {
            printf("%d\n",t.step);
            return ;
        }
        for (int i = 1; i <= 6; i++)
        {
            if (i == 1)
            {
                 sa = A;sb = t.b;
            }
            else if (i == 2)
            {
                 sa = t.a; sb = B;
            }
            else if (i == 3)
            {
                if (t.a + t.b > A)
                    {sb = t.a + t.b - A;sa = A;}
                else
                    {sb = 0; sa = t.a + t.b;}
            }
            else if (i == 4)
            {
                if (t.a + t.b > B)
                    {sa = t.a + t.b - B; sb = B;}
                else
                {
                    sa = 0; sb = t.a + t.b;
                }
            }
            else if (i == 5)
                {sa = 0; sb = t.b;}
            else
                {sa = t.a; sb = 0;}
            if (!vis[sa][sb])
            {
                vis[sa][sb] = 1;
                f.a = sa; f.b = sb;
                f.step = t.step + 1;
                q.push(f);
            }
        }
    }
    puts("impossible");
}

int main()
{
    while (scanf("%d%d%d", &A, &B, &C) != EOF)
    {
        memset(vis, 0, sizeof(vis));
        BFS();
    }
    return 0;
}


 



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值