搜索

搜索是个神奇的东西,分dfs及bfs等(鉴于我后面有个人说不只两种,因此加个“等”),即深度优先搜索和广度优先搜索等,一般来说,深搜要用到递归,而广搜用队列维护,并且一般的一般来说,广搜会比深搜优秀。搜索一般都比较盲目,所以会做很多的无用功,因此数据一般较小,就是这样,概念说不清,看例题吧。
T1
奇怪的电梯
有一种奇怪的电梯,每一层都可以停电梯,但是第i层只能向上或向下走k_i层楼,问从a层到b层至少要按几次电梯。
这道题很经典,用dfs的话,以dfs一条道走到黑的信念,搜起来麻烦,并且估计很有可以RE。那么用bfs搜索,我们以现在在第几层楼为参数,然后分两种情况去搜索,向上或向下,但是在搜索前必须进行判断,不能让它搜出来边界,否则就回不来了。用一个队列存储,将能走到但还未走过的楼层入队,然后再那一层楼向上或向下走k_i层,再次进行上述操作,直到走到目标楼层,当然,也有可能走不到那一层楼,所以我们可以设置一个vis数组标记这个点是否走过,这样不仅可以判断最后能否走到,也可以不走已走过的点。

#include<bits/stdc++.h>
using namespace std;
int t[250],vis[250],q[250],head=1,tail,k[250],a,b,n;
void bfs(int x)
{
    int top;
    t[a]=0;
    vis[a]=1;
    q[++tail]=a;
    if(x==b)
     return;
    while(head<=tail)
    {
        top=q[head++];
        vis[top]=1;
        if(top+k[top]<=n&&!vis[top+k[top]])//向上走k_i层不超过最高层,且那一层未走过
        {
            q[++tail]=top+k[top];
            vis[top+k[top]]=1;
            t[top+k[top]]=t[top]+1;//走到这一层的步数一定是上一层+1步
        }
        if(top-k[top]>0&&!vis[top-k[top]])//同理,向下走
        {
            q[++tail]=top-k[top];
            vis[top-k[top]]=1;
            t[top-k[top]]=t[top]+1;
        }
    }
}
int main()
{
    cin>>n>>a>>b;
    for(int i=1;i<=n;i++)
     cin>>k[i];
    bfs(a);
    if(vis[b])//判断是否走到
    cout<<t[b]<<endl;
    else
    cout<<-1<<endl;
    return 0;
}

T2
健康的荷斯坦奶牛
农夫知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。 给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。(每种饲料最多只能对牛使用一次)
这是dfs,但也可以不用dfs做,如果用dfs做就可以引入一种新的问题,选物品的问题,因为每种饲料只能使用一次,所以每一种饲料都只有选和不选两种情况,如果现在各种维生素已经到达标准,那么可以把这种方案存下来,和以后达到标准的进行比较,选出所需饲料剂最小的输出。

#include<bits/stdc++.h>
using namespace std;
int n,m,a[35],b[35][35],ans=10000000;
int Ans[35],Ans_[35];
int t,s[35]={};
int f()
{
    int p=1;
    for(int i=1;i<=n;i++)
     if (s[i]<a[i])
      {
        p=0;
        break;
      }
    return p;
}
void dfs(int x)
{

    if (t>=ans) return ;
    if(f())//判断是否满足条件,若满足就存储下来
    {
        ans=t;
        for(int i=1;i<=t;i++)
         Ans[i]=Ans_[i];
        return ;
    }
    if(x==m+1)//如果搜到了m+1种饲料,就只能跳出了,因为已经没有饲料了
    {
        return ;
    }
    for(int i=1;i<=n;i++)
     s[i]+=b[x][i];//统计各种维生素的量
    Ans_[++t]=x;
    dfs(x+1);//直接忽略,不选
    t--;
    for(int i=1;i<=n;i++)
     s[i]-=b[x][i];
    dfs(x+1);
} 
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
     cin>>a[i];
    cin>>m;
    for(int i=1;i<=m;i++)
     for(int j=1;j<=n;j++)
      cin>>b[i][j];
        dfs(1);//从第一种饲料开始判断
    cout<<ans<<' ';
    for(int i=1;i<=ans-1;i++)
     cout<<Ans[i]<<' ';
    cout<<Ans[ans];
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值