搜索——双端队列广搜&&双向广搜(BFS)

双端队列广搜

电路维修

原题链接

这里是引用

#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define int long long
#define fi first
#define se second
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef pair<int,int> pii;
const int N= 510;
char g[N][N];
int n,m;
int dist[N][N];
bool st[N][N];
int dx[4]={-1,-1,1,1},dy[4]={-1,1,1,-1};
int ix[4]={-1,-1,0,0},iy[4]={-1,0,0,-1};
pii pre[N][N];
int bfs(int x,int y){
    memset(dist,0x3f,sizeof dist);
    memset(st,false,sizeof st);
    deque<pii> q;
    q.push_front({x,y});
    dist[x][y]=0;
    char s[]="\\/\\/";
    while(q.size()){
        auto t=q.front();
        q.pop_front();
        // if(st[t.fi][t.se]) continue;
        // st[t.fi][t.se]=true;
        
        for(int i=0;i<4;i++){
            int tx=t.fi+dx[i],ty=t.se+dy[i];
            int sx=t.fi+ix[i],sy=t.se+iy[i];
            if(tx<0||tx>n||ty<0||ty>m) continue;
            // if(dist[tx][ty]!=inf) continue;不能在这判断了,因为第一次进队列的时候距离不一定是最小,因为有的路径权值为0,会更新
            int d=(g[sx][sy]!=s[i]);
            if(dist[tx][ty]>dist[t.fi][t.se]+d)
                if(d){
                    q.push_back({tx,ty});
                    dist[tx][ty]=dist[t.fi][t.se]+d;
                    pre[tx][ty]=t;
                }else{
                    q.push_front({tx,ty});
                    dist[tx][ty]=dist[t.fi][t.se]+d;
                    pre[tx][ty]=t;
                }
        }
        
    }
    return dist[n][m];
}

signed main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        cin>>n>>m;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                cin>>g[i][j];
        
        if(n+m&1){
            // puts("NO SOLUTION");//关闭同步流后,如果与c语言里面的输入输出混用会使输入输出顺序出现问题
            cout<<"NO SOLUTION"<<endl;
        }  
        else    cout<<bfs(0,0)<<endl;
        
        // pii ed={n,m};
        
        // while(true){
        //     cout<<ed.fi<<" "<<ed.se<<endl;
        //     if(ed.fi==0&&ed.se==0) break;
        //     ed=pre[ed.fi][ed.se];
        // }
    }
    
    return 0;
}

debug

  1. 不能用距离的初始化数值来判断跳过,因为权值有为0的时候,所以第一次进入队列的点不一定是最小的,要一直更新。
  2. 关闭同步流后,混用puts和cout,使得输入输出顺序发生变化。
  3. \这个要用转义符

总结

  1. 双向队列广搜是解决权值为0,1求最短问题的方法。
  2. \转义符的使用,字符串的定义——“\/\/”,{ }
  3. 这种权值为0,或者第一次进入队列不一定是距离最小的情况,不能用初始值跳过。
  4. 关闭同步流后一定要注意不要混用c语言中的输入输出。
  5. 当数组为long long时,inf要用0x3f3f3f3f3f3f3f3f,八个3f。

双向广搜

字串变换

原题链接

这里是引用

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<set>
#include<map>
#define int long long
#define fi first
#define se second
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef pair<int, int>pii;

const int N = 10;
string A,B;
string a[N],b[N];
int n;

int extend(queue<string> &q,map<string,int> &da,map<string,int> &db,string a[],string b[]){
    int d=da[q.front()];
    while(q.size()&&da[q.front()]==d){
        auto t=q.front();
        q.pop();
        for(int i=0;i<n;i++){
            for(int j=0;j<t.size();j++){
                if(t.substr(j,a[i].size())==a[i]){
                    string state=t.substr(0,j)+b[i]+t.substr(j+a[i].size());
                    if(db.count(state)) return da[t]+db[state]+1;
                    if(da.count(state)) continue;
                    q.push(state);
                    da[state]=da[t]+1;
                }
                
            }
        }
    }
    return 11;//这里注意返回一个不符要求的数,不要忘记了
}

int bfs(string A,string B){
    
    if(A==B) return 0;//注意特判一下
    queue<string> qa,qb;
    map<string,int> da,db;
    qa.push(A),qb.push(B);
    da[A]=0,db[B]=0;
    
    int t,step=0;
    
    
    while(qa.size()&&qb.size()){//这一步一定不能忘,队列不空
        
        if(qa.size()<=qb.size()){
            t=extend(qa,da,db,a,b);
        }
        else t=extend(qb,db,da,b,a);
    
        if(t<=10) return t;
        if(++step>10) return 11;//扩展的多少层
    }
    return 11;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin>>A>>B;
    while(cin>>a[n]>>b[n]) n++;
    int t=bfs(A,B);
    if(t<=10) cout<<t;
    else cout<<"NO ANSWER!";
    return 0;
}

debug

  1. bfs里面居然忘了while队列不空
  2. extend和bfs函数里面完了记得返回不符要求的数。
  3. 特判一定要注意
  4. substr前面要用t.substr(),front()不要忘记括号
  5. a[i]替换成b[i]

总结

  1. 双向广搜用于解空间非常的大,然后求最小这种性质
  2. 广搜的不走,两个队列,谁小就扩展谁,轮流扩展
  3. map就当距离的用法dist,然后注意判断有没有要用count函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值