2.1 最基础的穷竭搜索

2.1.4 部分和dfs

#include <iostream>
#include <cstdio>
using namespace std;
int n,             //读入n个数 1 <= n <= 20
    sum;           //和是否恰好为k(sum)
int numberset[20] = {0};

bool dfs(int x, int sumnow)
{
    if(x == n)
    {
        /*if(sumnow == sum)
            return true;
        else
            return false;*/
        return sumnow == sum;           //简化代码
    }
    else
    {
        /*dfs(x + 1, sum + numberset[i]); //选择加上当前数字

        dfs(x + 1, sum);                //选择不加*/
        /**注意这里是bool类型而不是void**/
        if(dfs(x + 1, sumnow + numberset[x]))
            return true;

        if(dfs(x + 1, sumnow))
            return true;

        return false;                   //这里是前面递归到底层后一层层返回 说明不论加不加都凑不出k
    }
}

int main()
{
    freopen("in.txt","r",stdin);
    cin >> n;
    for(int i = 0;i < n;i++)
    {
        cin >> numberset[i];
    }
    cin >> sum;

    if(dfs(0, 0))
        cout << "YES" << endl;
    else
        cout << "NO" << endl;
    return 0;
}

2.1.4 Lake Counting dfs

#include <iostream>
#include <cstdio>

using namespace std;
/**这里最开始一直错是因为!搞错了二维数组棋盘里x y对应关系!
***二维数组a[i][j] 每个a[i]里有j个 也就i行j列**/
char court[101][101];
int step[8][2] = {{-1, -1}, {-1, 1}, {1, 1}, {1, -1}, {-1, 0}, {1, 0}, {0, 1}, {0, -1}};
int m, n;  //园子的尺寸 m * n        n, m <= 100

void dfs(int x, int y)   //如果调用了dfs 说明此时坐标内的值就是W 所以一定有一步首先处理W为.
{
    if(x < 0 || y < 0 || x > m || y > n)
        return;
        //这个出口不是必要的吗?
        //原书中没有这个出口,但是是在下面进一步dfs的时候首先判断了是否在园子内
        //而设置这个出口就是先调用dfs,如果不在院子里直接返回,效果上是一样的

    court[x][y] = '.';

    for(int i = 0;i < 8; i++)
    {
        int tempx = x, tempy = y;
        tempx += step[i][0];
        tempy += step[i][1];
        if(court[tempx][tempy] == 'W')
            dfs(tempx, tempy);
    }
}

int main()
{
    freopen("in.txt","r",stdin);

    cin >> m >> n;
    for(int i = 0;i < m; i++)
        for(int j = 0;j < n; j++)
            cin >> court[i][j];

    int timecount = 0;             //记录调用dfs的次数

    for(int i = 0;i < m; i++)
    {
        for(int j = 0;j < n; j++)
        {
            if(court[i][j] == 'W')
            {
                dfs(i, j);
                timecount++;
            }
        }
    }

    cout << timecount;
    return 0;
}

2.1.5 走迷宫bfs

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

/**bfs实质上不是在“找”最短路径,而是一层一层走,也就是
如果要完成路径,必然要经过这些点,所以这本身就是最短路径
而不是通过比较“找”到最短路径**/

using namespace std;

typedef pair<int, int> P;

int n, m, //迷宫大小n * m
    sx, sy, gx, gy;
const int INF = 10000000;

int dis[101][101], //记录每个点对于七点的距离(起点便为0)
    movestep[4][2] = {{1,0}, {-1,0} , {0,1}, {0,-1}};//每一步可以向邻接的上下左右四格进行移动
char ditu[101][101];

///本题目的求sx,sy到gx,gy的最短距离
void bfs()
{
    queue<P> que;
    //将所有点相对于起点的距离初始为INF 这样一旦为INF说明还没有走过
    //如果bfs结束以后依然是INF说明这个点无法到达

    for(int i = 0;i < n;i++)
    {
        for(int j = 0;j < m;j++)
        {
            dis[i][j] = INF;
        }
    }

    que.push(P(sx,sy));
    dis[sx][sy] = 0; //起点相对于起点的距离设置为0

    while(que.size()) //只要队列不为空que.size()不为0 队列不空说明还有未判断的点
    {
        P p = que.front(); //取出队首元素
        que.pop(); //删除最前端元素

        if(p.first == gx && p.second == gy) //说明已经到达终点 dis[gx][gy]记录的就是sx sy到达gx gy所必须经过的距离(也就是最短距离)
            break;

        //对下一层次的拓展是通过这里的循环实现
        //每延展到下一深度的一个点就进入队列 之后继续找再下一个点
        //而不是像dfs那样借助递归层层深入 不行再返回
        int tempx, tempy;
        for(int i = 0;i < 4;i++)
        {
            tempx = p.first + movestep[i][0];
            tempy = p.second + movestep[i][1];

            //判断是否越界
            if(tempx >= 0 && tempy >= 0 && tempx < n && tempy < m && ditu[tempx][tempy] != '#' && dis[tempx][tempy] == INF)
            {
                que.push(P(tempx, tempy));
                dis[tempx][tempy] = dis[p.first][p.second] + 1;
            }
        }
    }

}

int main()
{
    freopen("in.txt","r",stdin);
    cin >> n >> m; //n行m列

    for(int i = 0;i < n; i++)
    {
        for(int j = 0;j < m; j++)
        {
            cin >> ditu[i][j];
            if(ditu[i][j] == 'S')
            {
                sx = i;
                sy = j;
            }
            if(ditu[i][j] == 'G')
            {
                gx = i;
                gy = j;
            }
        }
    }

    bfs();

    cout << dis[gx][gy];
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值