【算法提高——第二讲】搜索

来自:算法提高课

第二讲 搜索

2.1 Flood Fill

2.1.1 1097. 池塘计数

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,m;
char g[N][N];
bool inq[N][N]={false};
int X[8]={0,0,1,-1,-1,1,-1,1};
int Y[8]={1,-1,0,0,1,1,-1,-1};
struct Node{
    int x,y;
}node;

bool judge(int x,int y)
{
    if(x>=n||x<0||y>=m||y<0)
    {
        return false;
    }
    if(g[x][y]=='.'||inq[x][y]==true)
    {
        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]=true;
    while(!q.empty())
    {
        Node top=q.front();
        q.pop();
        for(int i=0;i<8;i++)
        {
            int newX=top.x+X[i];
            int newY=top.y+Y[i];
            if(judge(newX,newY))
            {
                node.x=newX,node.y=newY;
                q.push(node);
                inq[newX][newY]=true;
            }
        }
    }
}
int main()
{
    cin>>n>>m;
    getchar();
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            char c=getchar();
            g[i][j]=c;
        }
        getchar();
    }
    int ans=0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(g[i][j]=='W'&&inq[i][j]==false)
            {
                ans++;
                bfs(i,j);
            }
        }
    }
    cout<<ans;
    return 0;
}

2.1.2 1098. 城堡问题

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=60;
int m,n;
int g[N][N][5];
bool inq[N][N];
int X[]={0,-1,0,1},Y[]={-1,0,1,0};
map<int,int> mp;
struct Node{
    int x,y;
}node;
void init()
{
    mp[0]=3;
    mp[1]=4;
    mp[2]=1;
    mp[3]=2;
}
int judge(int x,int y,int flag)
{
    if(x>=m||x<0||y>=n||y<0)
    {
        return false;
    }
    if(g[x][y][flag]==1||inq[x][y]==true)
    {
        return false;
    }
    return true;
}

int bfs(int x,int y)
{
    int ans=1;
    queue<Node> q;
    node.x=x,node.y=y;
    q.push(node);
    inq[x][y]=true;
    while(!q.empty())
    {
        Node top=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int newX=top.x+X[i];
            int newY=top.y+Y[i];
            if(judge(newX,newY,mp[i]))
            {
                node.x=newX,node.y=newY;
                q.push(node);
                inq[newX][newY]=true;
                ans++;
            }
        }
    }
    return ans;
}

int main()
{
    cin>>m>>n;
    init();
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            int x;
            cin>>x;
            g[i][j][1]=x&1;
            g[i][j][2]=(x&2)>>1;
            g[i][j][3]=(x&4)>>2;
            g[i][j][4]=(x&8)>>3;
        }
    }
    int ans=0,s=0;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(inq[i][j]==false)
            {
                ans++;
                s=max(s,bfs(i,j));
            }
        }
    }
    cout<<ans<<endl<<s;
    return 0;
}

2.1.3 1106. 山峰和山谷

在这里插入图片描述
在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n;
int g[N][N];
bool inq[N][N];
int X[]={0,0,1,-1,-1,-1,1,1},Y[]={1,-1,0,0,-1,1,-1,1};
struct Node{
    int x,y;
}node;

bool judge(int x,int y,int sx,int sy)
{
    if(x>=n||x<0||y>=n||y<0)
    {
        return  false;
    }
    if(g[x][y]!=g[sx][sy]||inq[x][y]==true)
    {
        return false;
    }
    return true;
}

int bfs(int x,int y)
{
    queue<Node> q,sv;
    node.x=x,node.y=y;
    q.push(node);
    inq[x][y]=true;
    sv.push(node);
    while(!q.empty())
    {
        Node top=q.front();
        q.pop();
        for(int i=0;i<8;i++)
        {
            int newX=top.x+X[i],newY=top.y+Y[i];
            if(judge(newX,newY,x,y))
            {
                node.x=newX,node.y=newY;
                q.push(node);
                inq[newX][newY]=true;
                sv.push(node);
            }
        }
    }
    int h=0,l=0;
    bool flagh=true,flagl=true;
    while(!sv.empty())
    {
        Node top=sv.front();
        sv.pop();
        for(int i=0;i<8;i++)
        {
            int newX=top.x+X[i],newY=top.y+Y[i];
            if(!(newX>=n||newX<0||newY>=n||newY<0))
            {
                if(g[x][y]<g[newX][newY])
                {
                    flagh=false;
                }
                if(g[x][y]>g[newX][newY])
                {
                    flagl=false;
                }
            }
        }
    }
    if(flagh&&flagl)
    {
        return 2;
    }
    if(flagh)
    {
        return 1;
    }
    if(flagl)
    {
        return -1;
    }
    return 0;
}
int main()
{
    ios::sync_with_stdio(0);
    cin>>n;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cin>>g[i][j];
        }
    }
    int h=0,l=0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(inq[i][j]==false)
            {
                int x=bfs(i,j);
                if(x==2)
                {
                    h++;
                    l++;
                }
                else if(x==1) h++;
                else if(x==-1) l++;
            }
        }
    }
    cout<<h<<" "<<l;

    return 0;
}

2.2 最短路模型

2.2.1 1076. 迷宫问题

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n;
int g[N][N];
bool inq[N][N];
struct Node{
    int x,y;
}node;
Node pre[N][N];
int X[]={0,0,1,-1},Y[]={1,-1,0,0};

bool judge(int x,int y)
{
    if(x>=n||x<0||y>=n||y<0)
        return false;
    if(g[x][y]==1||inq[x][y]==true)
        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]=true;

    while(!q.empty())
    {
        Node top=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int newX=top.x+X[i],newY=top.y+Y[i];
            if(judge(newX,newY))
            {
                node.x=newX,node.y=newY;
                q.push(node);
                node.x=top.x,node.y=top.y;
                pre[newX][newY]=node;
                inq[newX][newY]=true;
            }
        }
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cin>>g[i][j];
        }
    }
    bfs(n-1,n-1);
    node.x=0,node.y=0;
    while(true)
    {
        cout<<node.x<<" "<<node.y<<endl;
        if(node.x==n-1&&node.y==n-1)
            break;
        node=pre[node.x][node.y];
    }
    return 0;
}

2.2.2 188. 武士风度的牛

在这里插入图片描述
在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=160;
int r,c;
int g[N][N];
bool inq[N][N];
int sx,sy,ex,ey;
int X[]={-2,-2,-1,-1,1,1,2,2};
int Y[]={-1,1,-2,2,2,-2,1,-1};
int dist[N][N];
struct Node{
    int x,y;
}node;

bool judge(int x,int y)
{
    if(x>=r||x<0||y>=c||y<0)
        return false;
    if(g[x][y]=='*'||inq[x][y]==true)
        return false;
    return true;
}

int bfs(int x,int y)
{
    queue<Node> q;
    node.x=x,node.y=y;
    q.push(node);
    inq[x][y]=true;

    while(!q.empty())
    {
        Node top=q.front();
        q.pop();
        for(int i=0;i<8;i++)
        {
            int newX=top.x+X[i],newY=top.y+Y[i];
            if(judge(newX,newY))
            {
                node.x=newX,node.y=newY;
                dist[newX][newY]=dist[top.x][top.y]+1;
                q.push(node);
                inq[newX][newY]=true;
            }
        }
    }
    return dist[ex][ey];
}
int main()
{
    cin>>c>>r;
    getchar();
    for(int i=0;i<r;i++)
    {
        for(int j=0;j<c;j++)
        {
            char ch=getchar();
            if(ch=='K')
            {
                sx=i,sy=j;
            }
            if(ch=='H')
            {
                ex=i,ey=j;
            }
            g[i][j]=ch;
        }
        getchar();
    }
    cout<<bfs(sx,sy);
    return 0;
}

2.2.3 1100. 抓住那头牛

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,k;
bool inq[N];
int dist[2*N];

int getX(int x,int flag)
{
    if(flag==0)
        x=2*x;
    else if(flag==1)
        x-=1;
    else x+=1;
    return x;
}
void bfs(int x)
{
    queue<int> q;
    q.push(x);
    inq[x]=true;
    dist[x]=0;

    while(!q.empty())
    {
        int top=q.front();
        q.pop();
        for(int i=0;i<3;i++)
        {
            int newX=getX(top,i);
            if(newX>=0&&newX<N&&inq[newX]==false)
            {
                q.push(newX);
                inq[newX]=true;
                dist[newX]=min(dist[newX],dist[top]+1);
            }
        }
    }
}
int main()
{
    cin>>n>>k;
    fill(dist,dist+2*N,1e9);
    bfs(n);
    cout<<dist[k];
    return 0;
}

2.3 多源BFS

2.3.1 173. 矩阵距离

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,m;
int g[N][N];
int dist[N][N];
int X[]={0,0,1,-1},Y[]={1,-1,0,0};
struct Node{
    int x,y;
}node;
bool judge(int x,int y)
{
    if(x>=n||x<0||y>=m||y<0)
        return false;
    if(g[x][y]=='1'||dist[x][y]!=-1)
        return false;
    return true;
}

void bfs()
{
    fill(dist[0],dist[0]+N*N,-1);
    queue<Node> q;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(g[i][j]=='1')
            {
                node.x=i,node.y=j;
                dist[i][j]=0;
                q.push(node);
            }
        }
    }

    while(!q.empty())
    {
        Node top=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int x=top.x+X[i],y=top.y+Y[i];
            if(judge(x,y))
            {
                node.x=x,node.y=y;
                q.push(node);
                dist[x][y]=dist[top.x][top.y]+1;
            }
        }
    }
}
int main()
{
    cin>>n>>m;
    getchar();
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            g[i][j]=getchar();
        }
        getchar();
    }
    bfs();
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            cout<<dist[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

2.4 最小步数模型

2.4.1 1107. 魔板

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
char g[2][4];
string st,ed;
map<string,int> dis;
map<string,pair<char,string> > pre;

void toM(string str)
{
    for(int i=0;i<4;i++)
    {
        g[0][i]=str[i];
    }
    for(int i=3,j=4;i>=0;i--,j++)
    {
        g[1][i]=str[j];
    }
}

string getStr()
{
    string str="";
    for(int i=0;i<4;i++)
    {
        str+=g[0][i];
    }
    for(int i=3;i>=0;i--)
    {
        str+=g[1][i];
    }
    return str;
}

string opA(string str)
{
    toM(str);
    for(int i=0;i<4;i++)
    {
        swap(g[0][i],g[1][i]);
    }
    return getStr();
}

string opB(string str)
{
    toM(str);
    char v0=g[0][3],v1=g[1][3];
    for(int i=2;i>=0;i--)
    {
        g[0][i+1]=g[0][i];
        g[1][i+1]=g[1][i];
    }
    g[0][0]=v0,g[1][0]=v1;
    return getStr();
}

string opC(string str)
{
    toM(str);
    char v=g[0][1];
    g[0][1]=g[1][1];
    g[1][1]=g[1][2];
    g[1][2]=g[0][2];
    g[0][2]=v;
    return getStr();
}

void bfs(string st)
{
    if(st==ed)
        return;
    queue<string> q;
    q.push(st);
    dis[st]=0;

    while(!q.empty())
    {
        string top=q.front();
        q.pop();
        string tmp[3];
        tmp[0]=opA(top);
        tmp[1]=opB(top);
        tmp[2]=opC(top);
        for(int i=0;i<3;i++)
        {
            if(dis.count(tmp[i])==0)
            {
                dis[tmp[i]]=dis[top]+1;
                pre[tmp[i]]=make_pair(i+'A',top);
                q.push(tmp[i]);
                if(tmp[i]==ed)
                    return;
            }
        }
    }
}
int main()
{
    for(int i=0;i<4;i++)
    {
        g[0][i]='1'+i;
        st+=g[0][i];
    }
    for(int i=3,j=5;i>=0;i--,j++)
    {
        g[1][i]='0'+j;
        st+=g[1][i];
    }
    for(int i=0;i<8;i++)
    {
        char c;
        cin>>c;
        ed+=c;
    }
    bfs(st);
    cout<<dis[ed]<<endl;
    string op="";
    while(st!=ed)
    {
        op+=pre[ed].first;
        ed=pre[ed].second;
    }
    reverse(op.begin(),op.end());
    if(op.length()!=0)
        cout<<op<<endl;
    return 0;
}

2.5 双端队列广搜

2.5.1 175. 电路维修

在这里插入图片描述
在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=510;
int T;
int r,c;
char g[N][N];
int dis[N][N];
bool st[N][N];
struct Node{
    int x,y;
}node;

bool judge(int x,int y)
{
    if(x>r||x<0||y>c||y<0)
    {
        return false;
    }
    return true;
}
int bfs()
{
    int X[]={-1,-1,1,1},Y[]={-1,1,1,-1};
    int ix[]={-1,-1,0,0},iy[]={-1,0,0,-1};
    char cs[]="\\/\\/";
    fill(dis[0],dis[0]+N*N,1e9);
    fill(st[0],st[0]+N*N,false);
    deque<Node> q;
    node.x=0,node.y=0;
    dis[0][0]=0;
    q.push_back(node);

    while(!q.empty())
    {
        Node top=q.front();
        q.pop_front();
        if(st[top.x][top.y]) continue;
        st[top.x][top.y]=true;

        for(int i=0;i<4;i++)
        {
            int newX=top.x+X[i],newY=top.y+Y[i];
            if(judge(newX,newY))
            {
                int cx=top.x+ix[i],cy=top.y+iy[i];
                int d=dis[top.x][top.y]+(g[cx][cy]!=cs[i]);
                if(d<dis[newX][newY])
                {
                    dis[newX][newY]=d;
                    node.x=newX,node.y=newY;
                    if(g[cx][cy]!=cs[i])
                    {
                        q.push_back(node);
                    }
                    else q.push_front(node);
                }
            }

        }
    }
    return dis[r][c];
}
int main()
{
    cin>>T;
    while(T--)
    {
        cin>>r>>c;
        for(int i=0;i<r;i++)
        {
            cin>>g[i];
        }
        int ans=bfs();
        if(ans==1e9)
            cout<<"NO SOLUTION"<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}

2.6 双向广搜

2.6.1 190. 字串变换

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=10;
int n;
string A,B;
string a[N],b[N];

int extend(queue<string> &q,map<string,int> &ha,map<string,int> &hb,string a[],string b[])
{
    int tmp=ha[q.front()];
    while(!q.empty()&&tmp==ha[q.front()])
    {
        string t=q.front();
        q.pop();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<t.length();j++)
            {
                if(t.substr(j,a[i].length())==a[i])
                {
                    string r=t;
                    r.replace(j,a[i].length(),b[i]);
                    if(hb.count(r)) return ha[t]+hb[r]+1;
                    if(ha.count(r)) continue;
                    ha[r]=ha[t]+1;
                    q.push(r);
                }
            }
        }
    }
    return 11;
}
int bfs()
{
    queue<string> qa,qb;
    map<string,int> ha,hb;
    ha[A]=0,hb[B]=0;
    qa.push(A);
    qb.push(B);

    int step=0;
    while((!qa.empty())&&(!qb.empty()))
    {
        int t;
        if(qa.size()<qb.size()) t=extend(qa,ha,hb,a,b);
        else t=extend(qb,hb,ha,b,a);
        if(t<=10)
            return t;
        if(++step==10) return -1;
    }
    return -1;
}
int main()
{
    cin>>A>>B;
    string x,y;
    while(cin>>x>>y)
    {
        a[n]=x,b[n]=y,n++;
    }
    int ans=bfs();
    if(ans==-1)
        cout<<"NO ANSWER!";
    else
        cout<<ans;
    return 0;
}

2.7 A*

2.7.1 178. 第K短路

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1010,E=200010;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
int n,m;
int S,T,K;
int h[N],rh[N],e[E],w[E],ne[E],idx;
int dist[N],f[N],cnt[N];
bool st[N];
void add(int h[],int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

void djk()
{
    fill(dist,dist+N,1e9);
    dist[T]=0;
    priority_queue<PII,vector<PII>,greater<PII> >heap;
    heap.push(make_pair(0,T));
    while(heap.size())
    {
        PII t=heap.top();
        heap.pop();
        int ver=t.second;
        if(st[ver]) continue;
        st[ver]=true;
        for(int i=rh[ver];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dist[j]>dist[ver]+w[i])
            {
                dist[j]=dist[ver]+w[i];
                heap.push(make_pair(dist[j],j));
            }
        }
    }
    for(int i=0;i<n;i++)
        f[i]=dist[i];
}

int a_star()
{
    priority_queue<PIII,vector<PIII>,greater<PIII> > heap;
    heap.push(make_pair(dist[S],make_pair(0,S)));
    while(heap.size())
    {
        PIII t=heap.top();
        heap.pop();
        int ver=t.second.second,distance=t.second.first;
        cnt[ver]++;
        if(cnt[T]==K) return distance;
        for(int i=h[ver];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(cnt[j]<K)
            {
                heap.push(make_pair(distance+w[i]+f[j],make_pair(distance+w[i],j)));
            }
        }
    }
    return -1;
}
int main()
{
    cin>>n>>m;
    fill(h,h+N,-1);
    fill(rh,rh+N,-1);
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(h,a,b,c),add(rh,b,a,c);
    }
    cin>>S>>T>>K;
    if(S==T) K+=1;

    djk();

    cout<<a_star();
    return 0;
}

2.7.2 179. 八数码

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
char g[3][3];
string a,b="12345678x";
unordered_map<string,pair<char,string> > pre;
void toG(string s)
{
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            g[i][j]=s[i*3+j];
        }
    }
}

string toS()
{
    string s="";
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            s+=g[i][j];
        }
    }
    return s;
}

void getXY(int &x,int &y)
{
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            if(g[i][j]=='x')
            {
                x=i,y=j;
                return;
            }
        }
    }
}
string opU(string s)
{
    toG(s);
    int x,y;
    getXY(x,y);

    if(x!=0)
    {
        swap(g[x][y],g[x-1][y]);
        return toS();
    }
    else return "";
}

string opD(string s)
{
    toG(s);
    int x,y;
    getXY(x,y);

    if(x!=2)
    {
        swap(g[x][y],g[x+1][y]);
        return toS();
    }
    else return "";
}

string opL(string s)
{
    toG(s);
    int x,y;
    getXY(x,y);

    if(y!=0)
    {
        swap(g[x][y],g[x][y-1]);
        return toS();
    }
    else return "";
}

string opR(string s)
{
    toG(s);
    int x,y;
    getXY(x,y);

    if(y!=2)
    {
        swap(g[x][y],g[x][y+1]);
        return toS();
    }
    else return "";
}
int bfs()
{
    if(a==b)
        return 0;
    queue<string> q;
    q.push(a);
    pre[a]=make_pair('*',"");
    map<int,char> op;
    op[0]='u';
    op[1]='d';
    op[2]='l';
    op[3]='r';
    while(q.size())
    {
        string t=q.front();
        q.pop();
        string tmp[4];
        tmp[0]=opU(t);
        tmp[1]=opD(t);
        tmp[2]=opL(t);
        tmp[3]=opR(t);
        for(int i=0;i<4;i++)
        {
            if(tmp[i]!=""&&pre.count(tmp[i])==0)
            {
                q.push(tmp[i]);
                pre[tmp[i]]=make_pair(op[i],t);
                if(tmp[i]==b)
                    return 1;
            }
        }
    }
    return -1;
}
int main()
{
    for(int i=0;i<9;i++)
    {
        char c;
        cin>>c;
        a+=c;
    }
    int t=bfs();
    if(t==-1)
        cout<<"unsolvable";
    else
    {
        string ans="";
        string tmp=b;
        while(tmp!=a)
        {
            ans+=pre[tmp].first;
            tmp=pre[tmp].second;
        }
        reverse(ans.begin(),ans.end());
        cout<<ans;
    }
    return 0;
}
//2 3 4 1 5 x 7 6 8

2.8 DFS之连通性模型

2.8.1 1112. 迷宫

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int k,n;
char g[N][N];
int sx,sy,ex,ey;
bool st[N][N];
int X[]={1,-1,0,0},Y[]={0,0,1,-1};

bool judge(int x,int y)
{
    if(x>=n||x<0||y>=n||y<0)
        return false;
    if(g[x][y]=='#'||st[x][y]==true)
        return false;
    return true;
}
bool dfs(int x,int y)
{
    if(g[x][y]=='#')
        return false;
    if(x==ex&&y==ey)
        return true;
    st[x][y]=true;
    for(int i=0;i<4;i++)
    {
        int newX=x+X[i],newY=y+Y[i];
        if(judge(newX,newY))
        {
            if(dfs(newX,newY)) return true;
        }
    }
    return false;
}
int main()
{
    cin>>k;
    while(k--)
    {
        cin>>n;
        for(int i=0;i<n;i++)
        {
            cin>>g[i];
        }
        cin>>sx>>sy>>ex>>ey;
        fill(st[0],st[0]+N*N,false);
        if(sx==ex&&sy==ey&&g[ex][ey]!='#')
            cout<<"YES"<<endl;
        else if(g[sx][sy]=='#'||g[ex][ey]=='#')
        {
            cout<<"NO"<<endl;
        }
        else
        {
            bool flag=dfs(sx,sy);
            if(flag)
                cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
    }
    return 0;
}


/* BFS
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int k,n;
char g[N][N];
int sx,sy,ex,ey;
bool st[N][N];
int X[]={1,-1,0,0},Y[]={0,0,1,-1};
struct Node{
    int x,y;
}node;
bool judge(int x,int y)
{
    if(x>=n||x<0||y>=n||y<0)
        return false;
    if(g[x][y]=='#'||st[x][y]==true)
        return false;
    return true;
}
bool bfs()
{
    if(g[sx][sy]=='#'||g[ex][ey]=='#')
        return false;
    fill(st[0],st[0]+N*N,false);
    queue<Node> q;
    node.x=sx,node.y=sy;
    q.push(node);
    st[sx][sy]=true;

    while(q.size())
    {
        Node t=q.front();
        q.pop();

        for(int i=0;i<4;i++)
        {
            int newX=t.x+X[i],newY=t.y+Y[i];
            if(judge(newX,newY))
            {
                node.x=newX,node.y=newY;
                q.push(node);
                st[newX][newY]=true;
                if(ex==newX&&ey==newY)
                    return true;
            }
        }
    }
    return false;
}
int main()
{
    cin>>k;
    while(k--)
    {
        cin>>n;
        for(int i=0;i<n;i++)
        {
            cin>>g[i];
        }
        cin>>sx>>sy>>ex>>ey;
        if(sx==ex&&sy==ey&&g[ex][ey]!='#')
            cout<<"YES"<<endl;
        else
        {
            bool flag=bfs();
            if(flag)
                cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
    }
    return 0;
}
*/

2.8.2 1113. 红与黑

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=30;
char g[N][N];
int ans;
int n,m;
int sx,sy;
int X[]={0,0,1,-1},Y[]={1,-1,0,0};
bool st[N][N];

bool judge(int x,int y)
{
    if(x>=n||x<0||y>=m||y<0)
        return false;
    if(st[x][y]==true||g[x][y]=='#')
        return false;
    return true;
}
void dfs(int x,int y)
{
    if(st[x][y]) return;
    st[x][y]=true;
    ans++;
    for(int i=0;i<4;i++)
    {
        int newX=x+X[i],newY=y+Y[i];
        if(judge(newX,newY))
        {
            dfs(newX,newY);
        }
    }
    return;
}
int main()
{
    while(true)
    {
        cin>>m>>n;
        if(m==n&&n==0)
            break;
        for(int i=0;i<n;i++)
        {
            cin>>g[i];
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(g[i][j]=='@')
                {
                    sx=i,sy=j;
                }
            }
        }
        ans=0;
        fill(st[0],st[0]+N*N,false);
        dfs(sx,sy);
        cout<<ans<<endl;
    }
    return 0;
}

2.9 DFS之搜索顺序

2.9.1 1116. 马走日

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=10;
int n,m,x,y;
bool st[N][N];
int ans;
int X[]={-1,1,-2,2,-2,2,-1,1},Y[]={-2,-2,-1,-1,1,1,2,2};

void dfs(int x,int y,int cnt)
{
    if(cnt==n*m)
    {
        ans++;
        return;
    }
    st[x][y]=true;
    for(int i=0;i<8;i++)
    {
        int newX=x+X[i],newY=y+Y[i];
        if(newX>=n||newX<0||newY>=m||newY<0) continue;
        if(st[newX][newY]) continue;
        dfs(newX,newY,cnt+1);
    }
    st[x][y]=false;
}
int main()
{
    std::ios::sync_with_stdio(0);
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>m>>x>>y;
        ans=0;
        dfs(x,y,1);
        cout<<ans<<endl;
    }
    return 0;
}

2.9.2 1117. 单词接龙

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=50;
string str[N],start;
int n;
bool st[N];
int ans;

bool judge(string s)
{
    for(int i=0;i<2*n;i++)
    {
        int _min=min(s.length(),str[i].length());
        for(int len=1;len<_min;len++)
        {
            if(s.substr(s.length()-len)==str[i].substr(0,len)&&st[i]==false)
            {
                return true;
            }
        }
    }
    return false;
}
void dfs(string s)
{
    if(judge(s))
    {
        string tmp="";
        for(int i=0;i<2*n;i++)
        {
            int _min=min(s.length(),str[i].length());
            for(int len=1;len<_min;len++)
            {
                if(s.substr(s.length()-len)==str[i].substr(0,len)&&st[i]==false)
                {
                    st[i]=true;
                    tmp=s+str[i].substr(len);
                    dfs(tmp);
                    st[i]=false;
                }
            }
        }
    }
    else
    {
        ans=max(ans,(int)s.length());
        return;
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>str[i];
    for(int i=n;i<2*n;i++) str[i]=str[i-n];
    cin>>start;
    string s="#"+start;
    dfs(s);
    cout<<ans-1<<endl;
    return 0;
}

2.9.3 1118. 分成互质组

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=11;
int n;
int p[N];
int group[N][N];
bool st[N];
int ans=N;
//g:第几组;gc:当前组内下标是什么;
//tc:当前组中共有多少元素;start:当前组可以从哪个下标开始搜
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}

bool check(int group[],int gc,int i)
{
    for(int j=0;j<gc;j++)
    {
        if(gcd(p[group[j]],p[i])>1)
            return false;
    }
    return true;
}
void dfs(int g,int gc,int tc,int start)
{
    if(g>=ans) return;
    if(tc==n) ans=g;

    bool flag=true;
    for(int i=start;i<n;i++)
    {
        if(!st[i]&&check(group[g],gc,i))
        {
            st[i]=true;
            group[g][gc]=i;
            dfs(g,gc+1,tc+1,i+1);
            st[i]=false;

            flag=false;
        }
    }
    if(flag) dfs(g+1,0,tc,0);
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>p[i];
    dfs(1,0,0,0);
    cout<<ans;
    return 0;
}

2.10 DFS之剪枝与优化

2.10.1 165. 小猫爬山

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=25;
int n,w;
int cat[N];
int sum[N];
bool st[N];
int ans=N;

bool cmp(int a,int b)
{
    return a>b;
}

void dfs(int u,int k)
{
    if(k>=ans) return;
    if(u==n)
    {
        ans=k;
        return;
    }

    for(int i=0;i<k;i++)
    {
        if(cat[u]+sum[i]<=w)
        {
            sum[i]+=cat[u];
            dfs(u+1,k);
            sum[i]-=cat[u];
        }
    }
    sum[k]=cat[u];
    dfs(u+1,k+1);
    sum[k]=0;
}
int main()
{
    cin>>n>>w;
    for(int i=0;i<n;i++) cin>>cat[i];

    sort(cat,cat+n,cmp);

    dfs(0,0);
    cout<<ans;
    return 0;
}

2.10.2 166. 数独

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=9;
char str[100];
int ones[1<<N],mp[1<<N];
int row[N],col[N],cell[3][3];

inline int lowbit(int x)
{
    return x&-x;
}
void init()
{
    for(int i=0;i<N;i++)
    {
        row[i]=(1<<N)-1;
        col[i]=(1<<N)-1;
    }
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            cell[i][j]=(1<<N)-1;
        }
    }
}
inline int get(int x,int y)
{
    return row[x]&col[y]&cell[x/3][y/3];
}

bool bfs(int cnt)
{
    if(cnt==0) return true;
    int x,y,minv=10;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            if(str[i*N+j]=='.')
            {
                int t=ones[get(i,j)];
                if(t<minv)
                {
                    x=i,y=j,minv=t;
                }
            }
        }
    }
    int t=get(x,y);
    for(;t!=0;t-=lowbit(t))
    {
        int n=mp[lowbit(t)];
        row[x]-=1<<n;
        col[y]-=1<<n;
        cell[x/3][y/3]-=1<<n;
        str[x*N+y]='1'+n;

        if(bfs(cnt-1)) return true;

        row[x]+=1<<n;
        col[y]+=1<<n;
        cell[x/3][y/3]+=1<<n;
        str[x*N+y]='.';
    }
    return false;
}
int main()
{
    for(int i=0;i<N;i++) mp[1<<i]=i;
    for(int i=0;i<(1<<N);i++)
    {
        int s=0;
        for(int j=i;j;j-=lowbit(j)) s++;
        ones[i]=s;
    }
    while(true)
    {
        init();
        cin>>str;
        if(str[0]=='e')
            break;
        int cnt=0;
        for(int i=0,k=0;i<N;i++)
        {
            for(int j=0;j<N;j++,k++)
            {
                if(str[k]!='.')
                {
                    int t=str[k]-'1';
                    row[i]-=1<<t;
                    col[j]-=1<<t;
                    cell[i/3][j/3]-=1<<t;
                }
                else cnt++;
            }
        }
        bfs(cnt);
        cout<<str<<endl;
    }
    return 0;
}

2.10.3 167. 木棒

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=70;
int sticks[N];
bool st[N];
int n;
int sum,length;

bool dfs(int u,int cur,int start)
{
    if(u*length==sum) return true;
    if(cur==length) return dfs(u+1,0,0);

    for(int i=start;i<n;i++)
    {
        int l=sticks[i];
        if(st[i]||cur+l>length) continue;
        st[i]=true;
        if(dfs(u,cur+l,i+1)) return true;
        st[i]=false;

        if(!cur||cur+l==length) return false;

        int j=i;
        while(j<n&&sticks[j]==sticks[i]) j++;
        i=j-1;

    }
    return false;
}
int main()
{
    while(true)
    {
        fill(st,st+N,false);
        sum=0,length=0;
        cin>>n;
        if(n==0) break;
        for(int i=0;i<n;i++)
        {
            cin>>sticks[i];
            sum+=sticks[i];
            length=max(length,sticks[i]);
        }
        sort(sticks,sticks+n);
        reverse(sticks,sticks+n);
        while(length<=sum)
        {
            if(sum%length==0&&dfs(0,0,0))
            {
                cout<<length<<endl;
                break;
            }
            length++;
        }
    }
    return 0;
}

2.10.4 168. 生日蛋糕

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=25,INF=1e9;
int n,m;
int minv[N],mins[N];
int R[N],H[N];
int ans=INF;

void dfs(int u,int v,int s)
{
    if(v+minv[u]>n) return;
    if(s+mins[u]>=ans) return;
    if(s+2*(n-v)/R[u+1]>=ans) return;

    if(!u)
    {
        if(v==n) ans=s;
        return;
    }

    for(int r=min(R[u+1]-1,(int)sqrt(n-v));r>=u;r--)
    {
        for(int h=min(H[u+1]-1,(n-v)/r/r);h>=u;h--)
        {
            int t=0;
            if(u==m) t=r*r;

            R[u]=r,H[u]=h;
            dfs(u-1,v+r*r*h,s+2*r*h+t);
        }
    }
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        minv[i]=minv[i-1]+i*i*i;
        mins[i]=mins[i-1]+2*i*i;
    }
    R[m+1]=H[m+1]=INF;
    dfs(m,0,0);
    if(ans==INF) cout<<0<<endl;
    else cout<<ans<<endl;
    return 0;
}

2.11 迭代加深

2.11.1 170. 加成序列

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n;
int path[N];

bool dfs(int u,int depth)
{
    if(u==depth) return path[u-1]==n;

    bool st[N]={false};
    for(int i=u-1;i>=0;i--)
    {
        for(int j=i;j>=0;j--)
        {
            int s=path[i]+path[j];
            if(s>path[u-1]&&s<=n&&!st[s])
            {
                st[s]=true;
                path[u]=s;
                if(dfs(u+1,depth)) return true;
            }
        }
    }
    return false;
}
int main()
{
    while(true)
    {
        cin>>n;
        if(n==0) break;
        int depth=1;
        path[0]=1;
        while(!dfs(1,depth)) depth++;

        for(int i=0;i<depth;i++)
        {
            cout<<path[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

2.12 双向DFS

2.12.1 171. 送礼物

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=50;
typedef long long LL;
int n,m,k;
int g[N];
int weights[1<<24],cnt;
int ans;
void dfs_1(int u,int s)
{
    if(u==k)
    {
        weights[cnt++]=s;
        return;
    }
    if((LL)s+g[u]<=m) dfs_1(u+1,s+g[u]);
    dfs_1(u+1,s);
}
void dfs_2(int u,int s)
{
    if(u==n)
    {
        int l=0,r=cnt-1;
        while(l<r)
        {
            int mid=l+r+1>>1;
            if((LL)weights[mid]+s<=m) l=mid;
            else r=mid-1;
        }
        if(weights[r]+s<=m)
            ans=max(ans,weights[r]+s);
        return;
    }
    if((LL)s+g[u]<=m) dfs_2(u+1,s+g[u]);
    dfs_2(u+1,s);
}
int main()
{
    cin>>m>>n;
    for(int i=0;i<n;i++) cin>>g[i];
    sort(g,g+n);
    reverse(g,g+n);
    k=n/2+2;
    dfs_1(0,0);
    sort(weights,weights+cnt);
    cnt=unique(weights,weights+cnt)-weights;
    dfs_2(k,0);
    cout<<ans;
    return 0;
}

2.13 IDA*

2.13.1 180. 排书

在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=15;
int n;
int q[N];
int w[5][N];

int f()
{
    int tot=0;
    for(int i=0;i+1<n;i++)
    {
        if(q[i+1]!=q[i]+1)
            tot++;
    }
    return (tot+2)/3;
}

bool check()
{
    for(int i=0;i<n;i++)
    {
        if(q[i]!=i+1)
            return false;
    }
    return true;
}

bool dfs(int depth,int max_depth)
{
    if(depth+f()>max_depth) return false;
    if(check()) return true;

    for(int len=1;len<=n;len++)
    {
        for(int l=0;l+len-1<n;l++)
        {
            int r=l+len-1;
            for(int k=r+1;k<n;k++)
            {
                memcpy(w[depth],q,sizeof q);
                int x,y;
                for(x=r+1,y=l;x<=k;x++,y++)
                {
                    q[y]=w[depth][x];
                }
                for(x=l;x<=r;x++,y++)
                {
                    q[y]=w[depth][x];
                }
                if(dfs(depth+1,max_depth)) return true;
                memcpy(q,w[depth],sizeof q);
            }
        }
    }
    return false;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>q[i];

        int depth=0;
        while(depth<5&&!dfs(0,depth)) depth++;

        if(depth>=5) cout<<"5 or more"<<endl;
        else cout<<depth<<endl;
    }
    return 0;
}

2.13.2 181. 回转游戏

在这里插入图片描述

代码:

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

int op[8][7]={
    {0,2,6,11,15,20,22},
    {1,3,8,12,17,21,23},
    {10,9,8,7,6,5,4},
    {19,18,17,16,15,14,13},
    {23,21,17,12,8,3,1},
    {22,20,15,11,6,2,0},
    {13,14,15,16,17,18,19},
    {4,5,6,7,8,9,10}
};
int oppsite[8]={5,4,7,6,1,0,3,2};
int center[8]={6,7,8,11,12,15,16,17};

int q[N];
int path[100];
int sum[4];
int f()
{
    fill(sum,sum+4,0);
    for(int i=0;i<8;i++)
        sum[q[center[i]]]++;
    int k=0;
    for(int i=1;i<=3;i++)
    {
        k=max(k,sum[i]);
    }
    return 8-k;
}
void operate(int x)
{
    int t=q[op[x][0]];
    for(int i=1;i<7;i++)
    {
        q[op[x][i-1]]=q[op[x][i]];
    }
    q[op[x][6]]=t;
}
bool dfs(int depth,int max_depth,int last)
{
    if(depth+f()>max_depth) return false;
    if(f()==0) return true;

    for(int i=0;i<8;i++)
    {
        if(oppsite[i]==last) continue;
        operate(i);
        path[depth]=i;
        if(dfs(depth+1,max_depth,i)) return true;
        operate(oppsite[i]);
    }
    return false;
}
int main()
{
    while(scanf("%d",&q[0]),q[0])
    {
        for(int i=1;i<N;i++)
        {
            scanf("%d",&q[i]);
        }
        int depth=0;
        while(!dfs(0,depth,-1)) depth++;
        if(!depth)
            puts("No moves needed");
        else
        {
            for(int i=0;i<depth;i++)
            {
                printf("%c",path[i]+'A');
            }
            puts("");
        }
        printf("%d\n",q[6]);
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值