• poj 几道简单的搜索题 (一)


    题目:poj 2488 A Knight's Journey
    题意:

    给一个m*n的棋盘,马走日,给出一条字典序最小的马的路线来走完整个棋盘?

    分析:

    如果能走完棋盘,那么从(1,1)点dfs即可,因为他能走完整个棋盘嘛,总有一步会经过(1,1),所以从(1,1)出发就能到其他所有点。

    为了保证字典序,在枚举方向时顺序要保证x轴优先,然后y轴。

    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=33;
    typedef pair<int,int>pii;
    vector<pii>ans;
    int dx[][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
    int n,m;
    bool vis[N][N];
    bool dfs(int x,int y,int step)
    {
        if(step==n*m)return 1;
        for(int i=0;i<8;i++){
            int xx=dx[i][0]+x;
            int yy=dx[i][1]+y;
            if(xx<1||yy<1||xx>n||yy>m||vis[xx][yy])continue;
            vis[xx][yy]=1;
            ans.push_back(make_pair(xx,yy));
            if(dfs(xx,yy,step+1)) return 1;
            vis[xx][yy]=0;
            ans.pop_back();
        }
        return 0;
    }
    int main()
    {
        int T;scanf("%d",&T);
        for(int cas=1;cas<=T;cas++){
            ans.clear();
            scanf("%d%d",&m,&n);
            ans.push_back(make_pair(1,1));
            memset(vis,0,sizeof(vis));
            vis[1][1]=1;
            printf("Scenario #%d:
    ",cas);
            if(dfs(1,1,1)){
                for(int i=0;i<ans.size();i++)
                    printf("%c%d",(char)('A'+ans[i].first-1),ans[i].second);
            }
            else printf("impossible");
            printf("
    
    ");
        }
        return 0;
    }

    题目:poj 3009

    题意:

    滚小球,小球刚开始在起点S,每次可以往四个方向扔出,扔出后小球一直滚动,直到碰到砖块(砖块碰到后消失)或者到达终点E。问小球到E的最短路?

    分析:

    虽然是到类似于最短路的题目,但是似乎bfs是不行的,因为每次球发生碰撞后会改变地图,有可能出现更优解!所以要dfs找出所有的可能解(所以数据范围才小),但是要剪枝,不然会超时。

    #include<cstdio>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int N=22;
    int g[N][N];
    int w,h,sx,sy;
    int dx[][2]={{-1,0},{1,0},{0,-1},{0,1}};
    int ans=INF;
    void dfs(int x,int y,int step)
    {
        if(step>=10||step>=ans)return; //剪枝
        for(int i=0;i<4;i++){
            int xx=dx[i][0]+x;
            int yy=dx[i][1]+y;
            if(g[xx][yy]==1)continue;
            while(xx>=0&&xx<w&&yy>=0&&yy<h&&g[xx][yy]!=1&&g[xx][yy]!=3)xx=dx[i][0]+xx,yy=dx[i][1]+yy;
            if(xx<0||xx==w||yy<0||yy==h)continue;
            if(g[xx][yy]==3){ans=step+1;return;} //每次更新,一定更优,因为上面已经剪过枝
            g[xx][yy]=0;
            dfs(xx-dx[i][0],yy-dx[i][1],step+1);
            g[xx][yy]=1;
        }
    }
    int main()
    {
        while(~scanf("%d%d",&w,&h)&&(w+h)){
            ans=INF;
            for(int j=0;j<h;j++)
            for(int i=0;i<w;i++){
                scanf("%d",&g[i][j]);
                if(g[i][j]==2)sx=i,sy=j;
            }
            dfs(sx,sy,0);
            if(ans==INF)printf("-1
    ");
            else printf("%d
    ",ans);
        }
        return 0;
    }

    题目:poj 1321

    题意:

    在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。

    每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n

    分析:

    要找所有方案,显然是要dfs找出所有可能解。因为放了的棋子不能在同一行或者同一列,很容易想到开两个数组标记一下有棋子的行和列,但是这似乎还不能解决这个问题,因为可能出现重复(比如这种方案是AB两点,另一种方案是BA两点),为了防止重复,可以逐行枚举,这样就不会出现重复的情况了。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=10;
    int n,k;
    bool visy[N],g[N][N];
    char s[N];
    int ans;
    void dfs(int row,int step)
    {
        if(step==k){
            ans++;return;
        }
        for(int i=row;i<n;i++)
            for(int j=0;j<n;j++){
                if(g[i][j]&&!visy[j]){
                    visy[j]=1;
                    dfs(i+1,step+1);
                    visy[j]=0;
                }
            }
    }
    int main()
    {
        while(~scanf("%d%d",&n,&k)&&(~n)){
            memset(visy,0,sizeof(visy));
            ans=0;
            int sx,sy;
            for(int i=0;i<n;i++){
                scanf("%s",s);
                for(int j=0;j<n;j++)
                    g[i][j]=s[j]=='#'?1:0;
            }
            dfs(0,0);
            printf("%d
    ",ans);
        }
        return 0;
    }


    题目:poj 2251

    题意:

    给出一个三维的图,求S到E的最短路

    分析:

    裸的bfs

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    #define mp make_pair
    const int N=33;
    typedef pair<int,int>pii;
    typedef pair<pii,pii>state; //步数,层,行,列,可能写个struct清晰点QAQ
    char g[N][N][N];
    bool vis[N][N][N];
    int C,L,R,sl,sc,sr; //层数,行数,列数,开始的层行列
    int d[][3]={{0,0,-1},{0,0,1},{0,-1,0},{0,1,0},{-1,0,0},{1,0,0}};
    int bfs()
    {
        queue<state>q;
        q.push(mp(mp(0,sl),mp(sr,sc)));
        memset(vis,0,sizeof(vis));
        vis[sl][sr][sc]=1;
        while(!q.empty()){
            state t=q.front();q.pop();
            int step=t.first.first,l=t.first.second,r=t.second.first,c=t.second.second;
            for(int i=0;i<6;i++){
                int tl=l+d[i][0],tr=r+d[i][1],tc=c+d[i][2];
                if(tl<0||tl==L||tr<0||tr==R||tc<0||tc==C||vis[tl][tr][tc]||g[tl][tr][tc]=='#')continue;
                if(g[tl][tr][tc]=='E')return step+1;
                vis[tl][tr][tc]=1;
                q.push(mp(mp(step+1,tl),mp(tr,tc)));
            }
        }
        return -1;
    }
    int main()
    {
        while(~scanf("%d%d%d",&L,&R,&C)&&(L+R+C)){
            for(int l=0;l<L;l++)
                for(int r=0;r<R;r++){
                    scanf("%s",g[l][r]);
                    for(int c=0;c<C;c++)if(g[l][r][c]=='S')sl=l,sr=r,sc=c;
                }
            int t=bfs();
            if(t==-1)printf("Trapped!
    ");
            else printf("Escaped in %d minute(s).
    ",t);
        }
        return 0;
    }










  • 相关阅读:
    防抖函数
    锁屏功能
    配置编译环境和线上环境之间的切换
    vue-router中的滚动行为
    axios的再次封装
    Anaconda 镜像配置
    Python 包管理工具 pip 与 conda
    Anaconda 安装与卸载
    VS Code 配置和使用
    解决 VS Code 无法使用Ctrl+C等快捷键
  • 原文地址:https://www.cnblogs.com/01world/p/5762842.html
Copyright © 2020-2023  润新知