[一本通学习笔记] 广度优先搜索和优化

BFS的题目没什么好说的,通常优化都是判断可行性,或者状压以后记忆化。几道例题都非常基础。

#10027. 「一本通 1.4 例 2」魔板

暴力写出置换即可。

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

int buf[9],tar,ans,src; char vis[99999999];
map <int,string > sta;

void A() {
    swap(buf[1],buf[5]); swap(buf[2],buf[6]);
    swap(buf[3],buf[7]); swap(buf[4],buf[8]);
}
void B() {
    int t1=buf[4], t2=buf[8];
    buf[4]=buf[3]; buf[8]=buf[7];
    buf[3]=buf[2]; buf[7]=buf[6];
    buf[2]=buf[1]; buf[6]=buf[5];
    buf[1]=t1; buf[5]=t2;
}
void C() {
    int t=buf[2];
    buf[2]=buf[6]; buf[6]=buf[7];
    buf[7]=buf[3]; buf[3]=t;
}

int compress() {
    int ret = 0;
    for(int i=1;i<=8;i++)
        ret=ret*10+buf[i];
    return ret;
}
void depress(int x) {
    for(int i=8;i>=1;--i)
        buf[i]=x%10, x/=10;
}

int main() {
    for(int i=1;i<=8;i++) cin>>buf[i];
    swap(buf[5],buf[8]);
    swap(buf[6],buf[7]);
    tar = compress();
    for(int i=1;i<=4;i++) buf[i]=i;
    for(int i=1;i<=4;i++) buf[8-i+1]=i+4;
    src = compress();
    queue <int> q;
    q.push(src);
    string v;
    sta[src]=v;
    vis[src]=1;
    while(!q.empty()) {
        int p = q.front(); q.pop();
        if(p==tar) {
            cout<<vis[p]-1<<endl;
            for(int i=0;i<sta[p].size();i++) cout<<sta[p][i];
            return 0;
        }
        int tmp;
        depress(p);
        A();
        tmp=compress();
        if(vis[tmp]==0) {
            vis[tmp]=vis[p]+1;
            sta[tmp]=sta[p];
            sta[tmp]+="A";
            q.push(tmp);
        }
        depress(p);
        B();
        tmp=compress();
        if(vis[tmp]==0) {
            vis[tmp]=vis[p]+1;
            sta[tmp]=sta[p];
            sta[tmp]+="B";
            q.push(tmp);
        }
        depress(p);
        C();
        tmp=compress();
        if(vis[tmp]==0) {
            vis[tmp]=vis[p]+1;
            sta[tmp]=sta[p];
            sta[tmp]+="C";
            q.push(tmp);
        }
    }
}

#10028. 「一本通 1.4 例 3」Knight Moves

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

const int dx[9] = {0,2,1,-1,-2,-2,-1,1,2},
          dy[9] = {0,1,2,2,1,-1,-2,-2,-1};
int n,l,sx,sy,tx,ty;
int f[305][305];

int main(){
    cin>>n;
    while(n--) {
        cin>>l>>sx>>sy>>tx>>ty;
        memset(f,0xff,sizeof f);
        queue <pair<int,int> >q;
        q.push(make_pair(sx,sy));
        f[sx][sy]=0;
        while(!q.empty()) {
            int px=q.front().first, py=q.front().second;
            q.pop();
            if(px==tx && py==ty) {
                break;
            }
            else {
                for(int i=1;i<=8;i++) {
                    int nx=px+dx[i], ny=py+dy[i];
                    if(nx<0 || ny<0 || nx>=l || ny>=l) continue;
                    if(f[nx][ny] < 0) {
                        f[nx][ny]=f[px][py]+1;
                        q.push(make_pair(nx,ny));
                    }
                }
            }
        }
        cout<<f[tx][ty]<<endl;
    }
}

#10029. 「一本通 1.4 练习 1」棋盘游戏

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

struct Status {
    char a[4][4];
    int compress() {
        int tmp = 0;
        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                tmp+=(a[i][j]-'0')*(1<<(i*4+j));
        return tmp;
    }
    void depress(int tmp) {
        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                a[i][j]=((tmp>>(i*4+j))&1) + '0';
    }
};

const int d[12][4] =  {{1,1,1,2},{1,2,1,3},{1,3,1,4},{2,1,2,2},{2,2,2,3},{2,3,2,4},
{3,1,3,2},{3,2,3,3},{3,3,3,4},{4,1,4,2},{4,2,4,3},{4,3,4,4}};

int f[100005];

int main() {
    Status st,en;
    for(int i=0;i<4;i++) {
        string str;
        cin>>str;
        for(int j=0;j<4;j++) st.a[i][j]=str[j];
    }
    for(int i=0;i<4;i++) {
        string str;
        cin>>str;
        for(int j=0;j<4;j++) en.a[i][j]=str[j];
    }
    int tar = en.compress();
    int src = st.compress();

    memset(f,0xff,sizeof f);
    f[src] = 0;
    queue <int> q;
    q.push(src);
    int cnt = 0;
    while(!q.empty()) {
        int p = q.front();
        q.pop();
        if(p==tar) break;
        Status s;

        for(int i=0;i<12;i++) {
            s.depress(p);
            swap(s.a[d[i][0]-1][d[i][1]-1],s.a[d[i][2]-1][d[i][3]-1]);
            int tmp = s.compress();
            if(f[tmp]<0) {
                f[tmp]=f[p]+1;
                q.push(tmp);
            }
        }
        for(int i=0;i<12;i++) {
            s.depress(p);
            swap(s.a[d[i][1]-1][d[i][0]-1],s.a[d[i][3]-1][d[i][2]-1]);
            int tmp = s.compress();
            if(f[tmp]<0) {
                f[tmp]=f[p]+1;
                q.push(tmp);
            }
        }
    }
    cout<<f[tar]<<endl;
}

#10030. 「一本通 1.4 练习 2」Keyboarding

一开始题目看错了WA了好几发

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

struct Status {
    int x,y,z;
    int compress() {
        return z*2500+y*50+x;
    }
    void decompress(int tmp) {
        x=tmp%50;
        y=(tmp/50)%50;
        z=tmp/2500;
    }
};
const int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int r,c;
string s,tab[55];
int f[26000005];
pair<int,int> g[55][55][4];

int main() {
    cin>>r>>c;
    for(int i=0;i<r;i++) cin>>tab[i];
    cin>>s;
    s+="*";
    for(int j=0;j<r;j++)
        for(int k=0;k<c;k++) {
            for(int l=0;l<4;l++) {
                int x=j,y=k;
                int me=tab[j][k];
                while(x>=0&&y>=0&&x<r&&y<c&&me==tab[x][y])
                    x+=dx[l],y+=dy[l];
                if(x<0)x=j; if(y<0)y=k;
                if(x>=r)x=j;if(y>=c)y=k;
                g[j][k][l]=make_pair(x,y);
            }
        }

    memset(f,0xff,sizeof f);
    f[0]=0;
    queue <int> q;
    int len = s.length();
    int cnt = 0;
    q.push(0);
    while(!q.empty()) {++cnt;
        int p=q.front(); q.pop();
        Status st;
        st.decompress(p);
        char me = tab[st.x][st.y];
        if(st.z==len) {
            cout<<f[p]<<endl;
            return 0;
        }
        for(int i=0;i<4;i++) {
            st.decompress(p);
            pair<int,int> to = g[st.x][st.y][i];
            st.x=to.first;
            st.y=to.second;
            int tmp=st.compress();
            if(f[tmp]<0) {
                f[tmp]=f[p]+1;
                q.push(tmp);
            }
        }
        st.decompress(p);
        if(tab[st.x][st.y]==s[st.z]) {
            st.z++;
            int tmp=st.compress();
            f[tmp]=f[p]+1;
            q.push(tmp);
        }
    }
    //cout<<cnt<<endl;
}

#10031. 「一本通 1.4 练习 3」移动玩具

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

struct Status {
    char a[4][4];
    int compress() {
        int tmp = 0;
        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                tmp+=(1<<(i*4+j))*(a[i][j]-'0');
        return tmp;
    }
    void decompress(int tmp) {
        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                a[i][j] = ((tmp>>(i*4+j))&1) + '0';
    }
};

int f[100005];
const int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};


int main() {
    Status St,En;
    int st,en;
    for(int i=0;i<4;i++) {
        string tmp;
        cin>>tmp;
        for(int j=0;j<4;j++)
            St.a[i][j]=tmp[j];
    }
    for(int i=0;i<4;i++) {
        string tmp;
        cin>>tmp;
        for(int j=0;j<4;j++)
            En.a[i][j]=tmp[j];
    }
    st = St.compress();
    en = En.compress();
    memset(f,0xff,sizeof f);
    queue <int> q;
    q.push(st);
    f[st]=0;
    while(q.size()) {
        int p = q.front();
        q.pop();
        if(p==en) {
            cout<<f[p]<<endl;
            return 0;
        }
        Status s;
        s.decompress(p);
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++) {
                if(s.a[i][j]=='0') continue;
                for(int l=0;l<4;l++) {
                    int nx=i+dx[l],ny=j+dy[l];
                    if(nx<0||ny<0||nx>3||ny>3) continue;
                    if(s.a[nx][ny]=='1') continue;
                    swap(s.a[nx][ny],s.a[i][j]);
                    int tmp = s.compress();
                    if(f[tmp]==-1) {
                        f[tmp]=f[p]+1;
                        q.push(tmp);
                    }
                    swap(s.a[nx][ny],s.a[i][j]);
                }
            }
        }
    }
}

 

上一篇:luogu P7446 [Ynoi2007] rfplca


下一篇:c++ 迷宫问题