2021-7-25算法学习(算法笔记269-282)

一、DFS

首先推荐一篇文章,深度优先遍历的8个简单小例题
介绍了DFS的一些经典例题


一个背包问题

有n件物品,每件物品的重量为w[i],价值为c[i]。现需要选出若干物品装入一个容量为V的背包中,使得在选入背包的物品重量和不超过容量V的前提下,让背包中物品的价值之和最大,求最大价值(1<=n<=20)

#include <stdlib.h>
#include <stdio.h>
const int maxn = 30;
/*有n件物品,每件物品的重量为w[i],价值为c[i]。
现需要选出若干物品装入一个容量为V的背包中,使
得在选入背包的物品重量和不超过容量V的前提下,
让背包中物品的价值之和最大,求最大价值(1<=n<=20)
*/

int w[maxn],c[maxn];
int n,v,maxValue=0;

void DFS(int index,int sumW,int sumC)
{
    if(index==n)
    {
        if(sumW<=v&&sumC>maxValue)
        {
            maxValue=sumC;
        }

        return;
    }

    //两条“岔路”
    //一、不选第index件
    DFS(index+1,sumW,sumC);
    //二、选择第index件
    DFS(index+1,sumW+w[index],sumC+c[index]);
}

//经过剪枝
void dfs(int index,int sumW,int sumC)
{
    if(index==n)  //完成对n件物品的选择
    {
        return;
    }

    //两个岔路
    //不选第index件
    dfs(index+1,sumW,sumC);

    //选第index件,但要先判断
    if(sumW+w[index]<=v)
    {
        if(sumC+c[index]>maxValue)
        {
            maxValue=sumC+c[index];
        }
        dfs(index+1,sumW+w[index],sumC+c[index]);
    }
}

int main()
{
    scanf("%d%d",&n,&v);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&w[i]);
    }
    for(int i=0;i<n;i++)
    {
        scanf("%d",&c[i]);
    }
    //DFS(0,0,0);
    dfs(0,0,0);
    printf("%d\n",maxValue);
    return 0;

}

全排列问题

#include<bits/stdc++.h>
using namespace std;
int n;
ve
ctor<int> ans;

void show()
{
    for(int i=0;i<ans.size();i++)
    {
        printf("%d ",ans[i]);
    }putchar('\n');
    return;
}
int vis[12];
void dfs(int num) //参数表明的是状态,全排列问题中的状态就是 现在已经搜了多少个数
{
    if(num==n+1)
    {
        show();
        return;
    }

    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            ans.push_back(i);
            vis[i]=1;
            dfs(num+1);
            ans.pop_back();//
            vis[i]=0;//这两行要返回原来的状态【回溯】
        }
    }


}


int main()
{
    cin>>n;
    dfs(1);
    return 0;
}

集合的枚举

#include<bits/stdc++.h>
using namespace std;
vector<int> ans;

int n;
void show()
{
    for(int i=0;i<ans.size();i++)
    {
        printf("%d ",ans[i]);
    }
    printf("\n");
    return;
}

void dfs(int num)
{
    if(num==n+1)
    {
        show();
        return;
    }

    dfs(num+1);
    
    ans.push_back(num);
    dfs(num+1);
    ans.pop_back();

}

int main()
{
    scanf("%d",&n);
    dfs(1);
}

二、BFS

//BFS模版

void BFS(int s)
{
    queue<int> q;
    q.push(s);

    while(!q.empty())
    {
        取出队首元素top
        访问队首元素top
        将队首元素出队
        将top的下一层结点中未曾入队的结点全部入队,并设置为已入队
    }
}

mxn矩阵 乘位置(x,y)与其上下左右四个位置相邻
求矩阵中块的个数

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;

int matrix[maxn][maxn];
int inq[maxn][maxn];
int n,m;
struct Node
{
    int x;
    int y;
} node;
int X[4] = {1, 0, -1, 0};
int Y[4] = {0, 1, 0, -1};

bool judge(int x,int y)
{
    if(x<0||y<0||x>=n||y>=m)
    {
        return false;
    }
    if(matrix[x][y]==0||inq[x][y]==1) return false;

    return true;
}

void BFS(int x, int y)
{
    queue<Node> q;
    node.x = x;
    node.y = y;
    q.push(node);
    inq[x][y] == 1;
    int i;
    while (!q.empty())
    {
        x = q.front().x;
        y = q.front().y;
        q.pop();
        for (i = 0; i < 4; i++)
        {
            int tx = x + X[i];
            int ty = y + Y[i];

            if (judge(tx,ty))
            {
                node.x = tx;
                node.y = ty;
                inq[tx][ty] = 1;
                q.push(node);
            }
        }
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            scanf("%d", &matrix[i][j]);
        }
    }
    int ans = 0;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            if (matrix[i][j] == 1 && inq[i][j] == 0)
            {
                ans++;
                BFS(i, j);
            }
        }
    }

    printf("%d", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值