4/6 深搜广搜专题+二分答案+单调队列

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4/6 深搜广搜专题+二分答案+单调队列相关的知识,希望对你有一定的参考价值。

经典迷宫问题:
P6207 [USACO06OCT] Cows on Skates G
1.广搜可用于查找最少需要的步数,而深搜可求出到达终点的路经数。
2.可开一个数组记录路径,最后用深搜回溯路径。注意起点和终点的设置,可能需要自行补上。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int r,c,way[155][155][2];
int dx[4]=-1,1,0,0;
int dy[4]=0,0,1,-1;
char mp[155][155];
bool vis[155][155];
struct node

    int x,y,s;
;
queue<node>q;
void dfs(int xx,int yy)

    if(!way[xx][yy][0]&&!way[xx][yy][1]) return;
    dfs(way[xx][yy][0],way[xx][yy][1]);
    cout<<way[xx][yy][0]<<" "<<way[xx][yy][1]<<endl;

signed main()

    cin>>r>>c;
    for(int i=1;i<=r;i++)
        for(int j=1;j<=c;j++)
        cin>>mp[i][j];
    vis[1][1]=1;
    q.push(node1,1,0);
    while(!q.empty())
    
        node cur=q.front();q.pop();
        int x=cur.x,y=cur.y;
        if(x==r&&y==c)
            break;
        for(int i=0;i<4;i++)
        
            int nx=x+dx[i],ny=y+dy[i];
            if(nx<=0||nx>r||ny<=0||ny>c) continue;
            if(!vis[nx][ny]&&mp[nx][ny]=='.')
            
                vis[nx][ny]=1;
                way[nx][ny][0]=x;way[nx][ny][1]=y;
                q.push(nodenx,ny,cur.s+1);
            
        
    
    dfs(r,c);
    cout<<r<<" "<<c<<endl;
    return 0;


2.动态迷宫问题
P3395 路障
在每秒结束后放上一个路障。
关键关键:::注意yes和no输出的格式,看错了即使全敲对了也零分。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2005;
int n,zx[N],zy[N];
int dx[4]=-1,1,0,0;
int dy[4]=0,0,1,-1;
int mp[N][N];
bool vis[N][N];
struct node

    int x,y,s;
;
queue<node>q;

signed main()

    int t;cin>>t;
    while(t--)
    
        while(!q.empty()) q.pop();
        memset(mp,0,sizeof(mp));
        memset(vis,0,sizeof(vis));
        int n;cin>>n;
        for(int i=1;i<=2*n-2;i++)
            cin>>zx[i]>>zy[i];
        vis[1][1]=1;
        q.push(node1,1,0);
        int flag=0;
        while(!q.empty())
        
            node cur=q.front();q.pop();
            int x=cur.x,y=cur.y,g=cur.s;
            if(x==n&&y==n)
            
                flag=1;break;
            
            mp[zx[g]][zy[g]]=1;
            for(int i=0;i<4;i++)
            
                int nx=x+dx[i],ny=y+dy[i];
                if(nx<=0||nx>n||ny<=0||ny>n)
                    continue;
                if(!vis[nx][ny]&&!mp[nx][ny])
                
                    vis[nx][ny]=1;q.push(nodenx,ny,g+1);
                
            
        
        if(flag)
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    
    return 0;


广搜的灵活应用:
P3906 Geodetic集合
1.先利用广搜对于每个点进行松弛操作,记录到达这个点最短路径的前驱点。
2.根据终点,和记录的前驱点,遍历回起点,记录遍历过的点,方便输出。

#include<bits/stdc++.h>
#define long long ll
using namespace std;
const int inf=0x3f3f3f3f;
const int N=105;
int n,m,k,g[N][N],dist[N],pre[N][N],num[N];
bool vis[N];
void bfs(int u,int v)

    memset(num,0,sizeof(num));
    memset(dist,inf,sizeof(dist));
    memset(vis,0,sizeof(vis));
    queue<int>q;dist[u]=0;
    q.push(u);
    while(!q.empty())
    
        int s=q.front();q.pop();
        if(vis[s]) continue;
        vis[s]=1;
        for(int i=1;i<=n;i++)
        
            if(g[s][i])
            
                if(dist[i]>dist[s]+1)
                
                    dist[i]=dist[s]+1;
                    pre[i][++num[i]]=s;
                    q.push(i);
                
                else if(dist[i]==dist[s]+1)
                    pre[i][++num[i]]=s;
            
        
    
    memset(vis,0,sizeof(vis));
    q.push(v);vis[v]=1;
    while(!q.empty())
    
        int s=q.front();q.pop();
        for(int i=num[s];i>=1;i--)
        
            if(!vis[pre[s][i]])
            
                vis[pre[s][i]]=1;
                q.push(pre[s][i]);
            
        
    
    for(int i=1;i<=n;i++)
        if(vis[i])
        cout<<i<<" ";
    cout<<endl;

signed main()

    cin>>n>>m;
    for(int i=1;i<=m;i++)
    
        int u,v;cin>>u>>v;
        g[u][v]=g[v][u]=1;
    
    cin>>k;
    while(k--)
    
        int u,v;cin>>u>>v;
        bfs(u,v);
    
    return 0;


深搜经典题目:
P2196 [NOIP1996 提高组] 挖地雷

#include<bits/stdc++.h>
#define long long ll
using namespace std;
const int inf=0x3f3f3f3f;
const int N=55;
int n,a[N],g[N][N],path[N],ans[N],mx,gg;
bool vis[N];
bool check(int u)

    for(int i=1;i<=n;i++)
    
        if(g[u][i]&&!vis[i])
            return 1;
    
    return 0;

void dfs(int id,int step,int sum)

    if(!check(id))
    
        if(mx<sum)
        
            mx=sum;gg=step;
            for(int i=1;i<=step;i++) ans[i]=path[i];
        
    
    for(int i=1;i<=n;i++)
    
        if(g[id][i]&&!vis[i])
        
            path[step+1]=i;
            vis[i]=1;
            dfs(i,step+1,sum+a[i]);
            vis[i]=0;
        
    

signed main()

    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
    
        int x;cin>>x;
        if(x)
            g[i][j]=1;
    
    for(int i=1;i<=n;i++)
    
        path[1]=i;
        vis[i]=1;
        dfs(i,1,a[i]);
        vis[i]=0;
    
    for(int i=1;i<=gg;i++)
        cout<<ans[i]<<" ";
    cout<<endl;
    cout<<mx<<endl;
    return 0;


P2920 [USACO08NOV]Time Management S
二分枚举起点。注意特判-1的情况!!

#include<bits/stdc++.h>
#define long long ll
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1005;
int n,ans,mx=inf;
struct work

    int st,ti,ed;
e[N];
bool cmp(work e1,work e2)

    return e1.ed<e2.ed;

bool check(int x)

    for(int i=1;i<=n;i++)
    
        x+=e[i].ti;
        if(x>e[i].ed)
            return 0;
    
    return 1;

signed main()

    cin>>n;
    for(int i=1;i<=n;i++)
    
        cin>>e[i].ti>>e[i].ed;
        e[i].st=e[i].ed-e[i].ti;
        mx=min(mx,e[i].st);
    
    sort(e+1,e+n+1,cmp);
    int l=0,r=mx;
    while(l<=r)
    
        int mid=(

以上是关于4/6 深搜广搜专题+二分答案+单调队列的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 深搜广搜

Blue:贪心,单调队列

深搜和广搜的原理及优缺点

oj 1792:迷宫 广搜和深搜

BZOJ_3316_JC loves Mkk_ 二分答案 + 单调队列

广搜和深搜