[kuangbin带你飞]专题一 简单搜索 (17/1000)

来源:互联网 发布:万国数据fm经理待遇 编辑:程序博客网 时间:2024/06/05 14:21

终于,做完了kuangbin大神带你飞的专题一之简单搜索,实在有一股无法言喻的感觉,每道题类型都差不多但细节实现却有点细微区别,所以14道题我就只当作5题了。。

棋盘问题

稍微变了点形的皇后问题,不能一行一行搜索,要一个一个格子搜索

include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int N=10;int n,k,ans;int R[N],C[N],a[N][N];char ch;void dfs(int row,int col,int num){    int NR,NC;    if (num==k+1) {        ans++;        return;    }    if(row!=n){        NC=col+1;        NR=row;        if (NC==n) {            NC=0;            NR++;        }        if(!a[row][col]&&!R[row]&&!C[col]){            R[row]=1;            C[col]=1;            dfs(NR,NC,num+1);            C[col]=0;            R[row]=0;            dfs(NR,NC,num);        }        else dfs(NR,NC,num);    } }int main(){    while(cin>>n>>k){        if (n==-1&&k==-1) return 0;        ans=0;        memset(a,0,sizeof(a));        memset(R,0,sizeof(R));        memset(C,0,sizeof(C));        for(int i=0;i<n;i++){            for(int j=0;j<n;j++){                cin>>ch;                if (ch=='.'){                    a[i][j]=1;                }                else if (ch=='#') {                    a[i][j]=0;                }            }        }        dfs(0,0,1);        cout<<ans<<endl;    }    return 0;}

Dungeon Master

三维BFS

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <queue>#include <set>const int N=30+10;using namespace std;struct state{    int z,x,y,step;};queue<state> Q;set<int> S;int L,R,C,goalx,goaly,goalz,X,Y,Z,code;char tmp;int dx[6]={1,-1,0,0,0,0},    dy[6]={0,0,1,-1,0,0},    dz[6]={0,0,0,0,1,-1};int a[N][N][N];void bfs(){    while(!Q.empty()){        state t=Q.front();Q.pop();        for(int i=0;i<6;i++){            X=t.x+dx[i];            Y=t.y+dy[i];            Z=t.z+dz[i];            if (a[Z][X][Y]==1||X<0||X>=R||Z<0||Z>=L||Y<0||Y>=C) continue;            code=10000*Z+100*X+Y;            if (X==goalx&&Y==goaly&&Z==goalz){                cout<<"Escaped in "<<t.step+1<<" minute(s)."<<endl;                return;            }            if (S.find(code)==S.end()){                S.insert(code);                state node={Z,X,Y,t.step+1};                Q.push(node);            }        }    }    cout<<"Trapped!"<<endl;}int main(){    while(cin>>L>>R>>C){        if (!L&&!R&&!C) break;        memset(a,0,sizeof(a));        S.clear();        while(!Q.empty()) Q.pop();        for(int i=0;i<L;i++){            for(int j=0;j<R;j++){                for(int k=0;k<C;k++){                    cin>>tmp;                    if(tmp=='S'){                        state first={i,j,k,0};                        Q.push(first);                        code=10000*i+100*j+k;                        S.insert(code);                        a[i][j][k]=0;                    }                    else if(tmp=='E'){                        goalz=i;                        goalx=j;                        goaly=k;                        a[i][j][k]=0;                    }                    else if(tmp=='#'){                        a[i][j][k]=1;                    }                    else if(tmp=='.'){                        a[i][j][k]=0;                    }                }            }        }        bfs();    }    return 0;}

Catch That Cow

BFS,数字变换,反过来找,能稍微剪一下枝

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <set>#include <queue>using namespace std;struct node{    int num,step;};int n,k,T,Step;int main(){    cin>>n>>k;    if (n==k){        cout<<0<<endl;        return 0;    }     queue<node> Q;    set<int> S;    node first={k,0};    Q.push(first);    S.insert(k);    while(!Q.empty()){        node t=Q.front();Q.pop();        for(int i=0;i<3;i++){            if (i==0) T=t.num+1;            else if (i==1) T=t.num-1;            else if ((i==2)&&(t.num%2==0)) T=t.num/2;            Step=t.step+1;            if (S.find(T)!=S.end()) continue;            if (T==n){                cout<<Step<<endl;                return 0;            }             node t1={T,Step};            Q.push(t1);            S.insert(T);        }    }    return 0;}

Fliptile

二进制枚举,位运算,只用枚举第一行就能确定整个棋盘的翻转情况

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>const int N=20+10;const int INF=0x3f3f3f3f;using namespace std;int dx[4]={0,0,-1,1},    dy[4]={-1,1,0,0};int n,m,k,tmp,ok,ans=INF,cnt;int a[N][N],vis[N][N],opr[N][N];void turn(int x,int y){    int X,Y;    a[x][y]=a[x][y]^1;    for(int i=0;i<4;i++){        X=x+dx[i];        Y=y+dy[i];        if (X<0||X>=n||Y<0||Y>=m) continue;        a[X][Y]=a[X][Y]^1;    }}int check(int r){    for(int i=0;i<m;i++){        if (a[r][i]) return 0;    }    return 1;}int main(){    cin>>n>>m;    for(int i=0;i<n;i++){        for(int j=0;j<m;j++){            cin>>a[i][j];        }    }    for(int i=0;i<=(1<<m)-1;i++){        cnt=0;        memset(vis,0,sizeof(vis));        for(int j=0;j<m;j++){            k=1<<j;            tmp=k&i;            if (tmp) {                vis[0][m-1-j]=1;                turn(0,m-1-j);                cnt++;            }        }        /*cout<<endl;        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cout<<a[i][j]<<' ';            }            cout<<endl;        }*/        for(int i=1;i<n;i++){            for(int j=0;j<m;j++){                if (a[i-1][j]) {                    turn(i,j);                    vis[i][j]=1;                    cnt++;                }            }        }        if (check(n-1)) {            if (cnt<ans){                ans=cnt;                for(int i=0;i<n;i++){                    for(int j=0;j<m;j++){                        opr[i][j]=vis[i][j];                    }                }            }        }        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                if (vis[i][j]) turn(i,j);            }        }    }    if (ans==INF) cout<<"IMPOSSIBLE"<<endl;    else {        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cout<<opr[i][j]<<' ';            }            cout<<endl;        }    }    return 0;}

Find The Multiple

依旧是反过来找,正难则反,深搜要自己限定深度,或用bfs

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>typedef unsigned long long ull;typedef long long ll;using namespace std;int n,ok;ull ans;void ids(ull num,int k,int dep){    if (ok==1) return;    if (num%n==0) {        ans=num;        ok=1;        return;    }    if (k==dep) return;    ids(num*10,k+1,dep);    ids(num*10+1,k+1,dep);}int main(){    while(cin>>n){        if (!n) break;        ok=0;        ids(1,1,19);        if (ok) cout<<ans<<endl;    }    return 0;}

Prime path

关键是数位的枚举

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <queue>#include <set>using namespace std;const int N=10000+10;struct node{    int num,step;};int t,n,m,tmp,Step,Num,number;int prime[N];void bfs(){    cin>>n>>m;    if (n==m){        cout<<0<<endl;        return;    }    queue<node> Q;    set<int> S;    node first={n,0};    Q.push(first);    S.insert(n);    while(!Q.empty()){        node t=Q.front();Q.pop();        for(int i=1;i<=1000;i*=10){            tmp=t.num / i % 10;            number=t.num-tmp*i;            Step=t.step+1;            for(int j=0;j<=9;j++){                Num=number+j*i;                //cout<<Num<<endl;                if (!prime[Num]||S.find(Num)!=S.end()||Num<1000) continue;                //cout<<Num<<endl;                if (Num==m){                    cout<<Step<<endl;                    return;                }                node t1={Num,Step};                Q.push(t1);                S.insert(Num);            }        }    }}int main(){    for(int i=2;i<=9999;i++) prime[i]=1;    for(int i=2;i<=9999;i++){        if (prime[i]){            for(int j=i*i;j<=9999;j+=i){                prime[j]=0;            }        }    }    cin>>t;    while(t--) bfs();    return 0;}

Shuffle’m Up

模拟题,体会一下模拟与搜索的区别

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <string>#include <set>using namespace std;int t,len,step,kase;string s1,s2,s3;set<string> S;int main(){    cin>>t;    while(t--){        kase++;        cin>>len;        cin>>s1>>s2>>s3;        step=0;        while(1){            step++;            string tmp="";            for(int i=0;i<len;i++){                tmp+=s2[i];                tmp+=s1[i];            }            //cout<<tmp<<endl;            if (S.find(tmp)!=S.end()){                cout<<kase<<' '<<-1<<endl;                break;            }            S.insert(tmp);            if (tmp==s3) {                cout<<kase<<' '<<step<<endl;                break;            }            s1="";            s2="";            for(int i=0;i<len;i++){                s1+=tmp[i];            }            for(int i=len;i<2*len;i++){                s2+=tmp[i];            }        }    }    return 0;}

Pots

倒水问题+记录路径

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <string>#include <queue>const int N=100+10;using namespace std;string str[6]={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};struct node{    int a,b;    string s;};void print(string st){    cout<<st.length()<<endl;    for(int i=0;i<st.length();i++){        cout<<str[st[i]-'0']<<endl;    }}int A,B,C;int vis[N][N];int main(){    cin>>A>>B>>C;    queue<node> Q;    Q.push((node){0,0});    vis[0][0]=1;    while(!Q.empty()){        node t=Q.front();Q.pop();        for(int i=0;i<6;i++){            node tmp=t;            //cout<<tmp.a<<' '<<tmp.b<<endl;            if (i==0){                tmp.a=A;                tmp.s+='0';            }            else if (i==1){                tmp.b=B;                tmp.s+='1';            }            else if (i==2){                tmp.a=0;                tmp.s+='2';            }            else if (i==3){                tmp.b=0;                tmp.s+='3';            }            else if (i==4){                if (tmp.a+tmp.b<=B){                    tmp.b+=tmp.a;                    tmp.a=0;                }                else {                    tmp.a=tmp.a-(B-tmp.b);                    tmp.b=B;                }                tmp.s+='4';            }            else if (i==5){                if (tmp.b+tmp.a<=A){                    tmp.a+=tmp.b;                    tmp.b=0;                }                else {                    tmp.b=tmp.b-(A-tmp.a);                    tmp.a=A;                }                tmp.s+='5';            }            //cout<<tmp.a<<' '<<tmp.b<<endl<<endl;            if (vis[tmp.a][tmp.b]) continue;            if (tmp.a==C||tmp.b==C){                print(tmp.s);                return 0;            }            Q.push(tmp);            vis[tmp.a][tmp.b]=1;        }    }    cout<<"impossible"<<endl;    return 0;}

Fire Game

用cnt记录草数,可判断是否全部稍晚,还有一个小技巧是,一开始队列入两个着火点

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <queue>const int N=10+10;const int INF=0x3f3f3f3f;using namespace std;struct node{    int x,y; };int dx[4]={0,0,-1,1},    dy[4]={-1,1,0,0};int t,n,m,ans,kase,cnt,now,X,Y,tmp;int T[N][N],a[N][N];char ch;void bfs(int A,int b,int c,int d){    //cout<<A<<b<<c<<d<<endl;    now=2;    if (A==c&&b==d) now--;    tmp=0;    memset(T,-1,sizeof(T));    queue<node> Q;    Q.push((node){A,b});T[A][b]=0;    Q.push((node){c,d});T[c][d]=0;    while(!Q.empty()){        node t=Q.front();Q.pop();        for(int i=0;i<4;i++){            X=t.x+dx[i];            Y=t.y+dy[i];            if (X<0||X>=n||Y<0||Y>=m) continue;            if (!a[X][Y]) continue;            if (T[X][Y]!=-1) continue;            now++;            Q.push((node){X,Y});            T[X][Y]=T[t.x][t.y]+1;            tmp=max(T[X][Y],tmp);        }    }    if (now==cnt) ans=min(tmp,ans);}int main(){    cin>>t;    while(t--){        cin>>n>>m;        ans=INF;        kase++;        cnt=0;        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cin>>ch;                if (ch=='.') a[i][j]=0;                else {                    cnt++;                    a[i][j]=1;                }            }        }        for(int i=0;i<n;i++)            for(int j=0;j<m;j++)                for(int k=0;k<n;k++)                    for(int L=0;L<m;L++)                        if (a[i][j]&&a[k][L]){                            bfs(i,j,k,L);                        }        /*for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cout<<T[i][j]<<' ';            }            cout<<endl;        }*/        if (ans==INF) ans=-1;        cout<<"Case "<<kase<<": "<<ans<<endl;    }    return 0;}

Fire!

坑点在着火点可能不止一个

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <queue>const int N=1000+10;using namespace std;struct node{    int x,y;};int dx[4]={0,0,-1,1},    dy[4]={-1,1,0,0};char tmp;int t,n,m,x1,y1,x2,y2,flag,X,Y;int a[N][N],vis[N][N],D[N][N],T[N][N];void bfs(int x,int y){    queue<node> Q;    memset(vis,0,sizeof(vis));    node first={x,y};    Q.push(first);    vis[x][y]=1;    while(!Q.empty()){        node t=Q.front();Q.pop();        for(int i=0;i<4;i++){            X=t.x+dx[i];            Y=t.y+dy[i];            if (X<0||X>=n||Y<0||Y>=m) {                if (flag==0){                    cout<<D[t.x][t.y]+1<<endl;                    return;                }                else continue;            }            if (vis[X][Y]) continue;            if (a[X][Y]) continue;            if (flag) {                if (T[t.x][t.y]+1>=T[X][Y]) continue;                T[X][Y]=T[t.x][t.y]+1;            }            else {                if (D[t.x][t.y]+1>=T[X][Y]) continue;                D[X][Y]=D[t.x][t.y]+1;            }            node t1={X,Y};            Q.push(t1);            vis[X][Y]=1;        }    }    if (flag==0) cout<<"IMPOSSIBLE"<<endl;}int main(){    freopen("in.txt","r",stdin);    freopen("out.txt","w",stdout);    cin>>t;    while(t--){        memset(a,0,sizeof(a));        memset(T,0x3f,sizeof(T));        memset(D,0,sizeof(D));        cin>>n>>m;        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cin>>tmp;                if (tmp=='J'){                    x2=i;                    y2=j;                }                else if (tmp=='F'){                    T[i][j]=0;                }                else if(tmp=='#'){                    a[i][j]=1;                }            }        }        flag=1;        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                if (T[i][j]==0) bfs(i,j);            }        }        flag=0;        bfs(x2,y2);        /*for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cout<<T[i][j]<<' ';            }            cout<<endl;        }        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cout<<D[i][j]<<' ';            }            cout<<endl;        }*/    }    return 0;}/*24 4#####JF##..##..#3 3####J.#.F */

迷宫问题

如何记录路径,这是个问题,可以开两个二维数组记录上一个位置在那里,或者用开一个结构体数组保存,或者用string记录

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <set>#include <queue>const int N=5+5;using namespace std;struct node{    int x,y,step;};int dx[4]={0,0,-1,1},    dy[4]={-1,1,0,0};int code,Nx,Ny,Ns;int a[N][N],Lx[N][N],Ly[N][N];set<int> S;queue<node> Q;void print(int x,int y){    if(x==-1&&y==-1) return;    print(Lx[x][y],Ly[x][y]);    printf("(%d, %d)\n",x,y);}int main(){    for(int i=0;i<5;i++){        for(int j=0;j<5;j++){            cin>>a[i][j];        }    }    code=0;    S.insert(code);    node first={0,0,0};    Q.push(first);    Lx[0][0]=-1;    Ly[0][0]=-1;    while(!Q.empty()){        node tmp=Q.front();Q.pop();        for(int i=0;i<4;i++){            Nx=tmp.x+dx[i];            Ny=tmp.y+dy[i];            Ns=tmp.step+1;            if (Nx<0||Nx>=5||Ny<0||Ny>=5||a[Nx][Ny]) continue;            code=10*Nx+Ny;            if(S.find(code)==S.end()){                node t={Nx,Ny,Ns};                Lx[Nx][Ny]=tmp.x;                Ly[Nx][Ny]=tmp.y;                Q.push(t);                S.insert(code);            }            if(Nx==4&&Ny==4){                print(4,4);                return 0;            }        }    }    return 0;}

Oil Deposits

联通块问题

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>const int N=100+10;using namespace std;char tmp;int n,m,cnt;int a[N][N],vis[N][N];int dx[8]={-1,-1,-1, 0, 0, 1, 1, 1},    dy[8]={-1, 0, 1,-1, 1,-1, 0, 1};void dfs(int x,int y){    int x1,y1;    vis[x][y]=1;    for(int i=0;i<8;i++){        x1=x+dx[i];        y1=y+dy[i];        if (a[x1][y1]&&!vis[x1][y1]&&x1>=0&&x1<n&&y1>=0&&y1<m) dfs(x1,y1);    }}int main(){    while(1){        cin>>n>>m;        if (!n&&!m) break;        cnt=0;        memset(a,0,sizeof(a));        memset(vis,0,sizeof(vis));        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cin>>tmp;                if (tmp=='@') a[i][j]=1;                else a[i][j]=0;            }        }        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                if (a[i][j]&&!vis[i][j]) {                    cnt++;                    dfs(i,j);                }            }        }        cout<<cnt<<endl;    }    return 0;}

非常可乐

倒水问题,很明显S需要是偶数,这里可以稍微剪一下枝

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <queue>const int N=100+10;using namespace std;struct node{    int v[3],step;};int m[3],t1[3],s,vis[N][N][N];int ok(int a,int b,int c){    if (a==b&&c==0) return 1;    if (a==c&&b==0) return 1;    if (b==c&&a==0) return 1;    return 0;}void bfs(){    memset(vis,0,sizeof(vis));    queue<node> Q;    node first={0,0,m[2],0};    Q.push(first);    vis[0][0][m[2]]=1;    while(!Q.empty()){        node t=Q.front();Q.pop();        s=t.step+1;        for(int i=0;i<3;i++){            if (!t.v[i]) continue;            for(int j=0;j<3;j++){                if (i!=j&&t.v[j]<m[j]){                    for(int i=0;i<3;i++) t1[i]=t.v[i];                    if (t.v[i]+t.v[j]<=m[j]){                        t1[j]=t1[i]+t1[j];                        t1[i]=0;                        }                    else{                        t1[i]=t1[i]-(m[j]-t1[j]);                        t1[j]=m[j];                    }                    if (vis[t1[0]][t1[1]][t1[2]]) continue;                    if (ok(t1[0],t1[1],t1[2])) {                        cout<<s<<endl;                        return;                    }                    node T={t1[0],t1[1],t1[2],s};                    Q.push(T);                    vis[t1[0]][t1[1]][t1[2]]=1;                }            }        }    }    cout<<"NO"<<endl;}int main(){    while(1){        scanf("%d%d%d",&m[2],&m[0],&m[1]);        if (!m[0]&&!m[1]&&!m[2]) break;        if (m[2]%2){            cout<<"NO"<<endl;            continue;        }        bfs();    }    return 0;}

Find a way

要注意有些KFC是不能到达的

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <queue>#include <set>const int N=200+10;using namespace std;char tmp;int n,m,k,code,x1,y1,x2,y2,X,Y,ans,flag,cnt;int a[N][N],D[N][N],D1[N][N];int dx[4]={-1,1,0,0},    dy[4]={0,0,-1,1};struct node{    int x,y;};queue<node> Q;set<int> S;void bfs(){    while(!Q.empty()&&k<cnt){        node t=Q.front();Q.pop();        for(int i=0;i<4;i++){            X=t.x+dx[i];            Y=t.y+dy[i];            if (X<0||X>=n||Y<0||Y>=m||a[X][Y]==1) continue;            code=1000*X+Y;            if (S.find(code)==S.end()){                node t1={X,Y};                Q.push(t1);                S.insert(code);                if (flag==0) D[X][Y]=D[t.x][t.y]+1;                else D1[X][Y]=D1[t.x][t.y]+1;                if (a[X][Y]==2) k++;            }        }    }}int main(){    while(cin>>n>>m){        cnt=0;        memset(a,0,sizeof(a));        memset(D,0,sizeof(D));        memset(D1,0,sizeof(D1));        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cin>>tmp;                if (tmp=='Y') {                    x1=i;                    y1=j;                }                else if (tmp=='M'){                    x2=i;                    y2=j;                }                else if (tmp=='@'){                    a[i][j]=2;                    cnt++;                }                else if (tmp=='#'){                    a[i][j]=1;                }            }        }        while (!Q.empty()) Q.pop();        S.clear();        node first={x1,y1};        Q.push(first);        S.insert(1000*x1+y1);        k=0;        flag=0;        bfs();        /*for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cout<<D[i][j]<<' ';            }            cout<<endl;        }*/        while (!Q.empty()) Q.pop();        S.clear();        node first1={x2,y2};        Q.push(first1);        S.insert(1000*x2+y2);        k=0;        flag=1;        bfs();        /*for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                cout<<D1[i][j]<<' ';            }            cout<<endl;        }*/        ans=0x3f3f3f3f;        for(int i=0;i<n;i++){            for(int j=0;j<m;j++){                if (a[i][j]==2&&D[i][j]&&D1[i][j]) ans=min(ans,D[i][j]+D1[i][j]);            }        }        cout<<ans*11<<endl;    }    return 0;}
阅读全文
0 0