1 条题解

  • 0
    @ 2025-8-24 21:43:36

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar IRipple
    刹那余烬,是曾经鲜活跃动的记忆中铭刻至深的梦。

    搬运于2025-08-24 21:43:36,当前版本为作者最后更新于2019-04-11 13:15:59,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    很有意思的一道题,做法不是很难。但是卡住了机房大佬

    理论分析

    模拟一下走的过程。

    第一次走的时候我们到起点的上下左右四个方向都需要0个镜子,我们把这些点都记录成第一次的扩展。

    //拿样例来举个栗子,不妨设上面的C是起点,另一个是终点
    ....... 
    ......C 
    ......* 
    *****.* 
    ....*.. 
    ....*.. 
    .C..*.. 
    ....... 
    

    那么我们标记出第一次可以确定的点

    ......1 
    111111C 
    ......* 
    *****.* 
    ....*.. 
    ....*.. 
    .C..*.. 
    ....... 
    

    所有被标记为1的点,都不需要平面镜,我们接着走第二步。

    第二步我们把所有标记为1的点进行同样的操作,把这些点的上下左右扩展出来,记录成第二步扩展

    2222221 
    111111C 
    222222* 
    *****2* 
    ....*2. 
    ....*2. 
    .C..*2. 
    .....2. 
    

    所有被标记为2的点,都需要1个平面镜。

    ... ...

    像这样我们不断地扩展下去,就会得到到C点所需的镜子个数 0.0

    代码实现

    首先这种跑地图还问你最短xx的,我们就可以上bfs了。

    设计一个结构体

    struct node{
        int x,y;//点坐标
        int num;//记录这个点是第几步扩展得来的
    }s,t;
    

    然后随手敲一下bfs就行了

    void bfs(){
        while(!q.empty()){
            node u=q.front(),v=u;//u和v都是队首
            q.pop();
            u.num++;
            v=u; v.x=u.x-1;//上 
            dfs(1,v);
            v=u; v.x=u.x+1;//下 
            dfs(2,v);
            v=u; v.y=u.y-1;//左 
            dfs(3,v);
            v=u; v.y=u.y+1;//右 
            dfs(4,v);
        }
    }
    

    用这个bfs扩展队首点的四个方向,每次dfs去进行染色的工作

    void dfs(int fx,node u){ //fx记录方向(1上2下3左4右) u为当前所在点 
        int x=u.x,y=u.y,p=u.num; 
        if(a[x][y]<p || a[x][y]==inf) return;//如果该点标记比这次扩展的小【即更优】,就直接跳过它。
        									//inf表示墙,返回
        if(x<1 || y<1 || x>n || y>m) return;//超出边界返回
        if(fx==1){
            a[x][y]=p;//染色
            q.push((node){x,y,p});//放入队列,之后进行拓展
            dfs(1,(node){x-1,y,p});//染下一个上边的点
        }
        if(fx==2){
            a[x][y]=p;
            q.push((node){x,y,p});
            dfs(2,(node){x+1,y,p});
        }
        if(fx==3){
            a[x][y]=p;
            q.push((node){x,y,p});
            dfs(3,(node){x,y-1,p});
        }
        if(fx==4){
            a[x][y]=p;
            q.push((node){x,y,p});
            dfs(4,(node){x,y+1,p});
        }
    }
    

    说明:我把数据给出的地图转成了int类型,inf代表墙。

    完整代码如下~

    #include<bits/stdc++.h>
    #include<queue>
    #define inf 0x3f3f3f3f
    using namespace std;
    int n,m;
    int a[110][110];//保存地图
    struct node{
        int x,y;
        int num;
    }s,t;
    queue<node> q;
    void dfs(int fx,node u){ //fx记录方向(1上2下3左4右) u为当前所在点 
        int x=u.x,y=u.y,p=u.num; 
        if(a[x][y]<p || a[x][y]==inf) return;
        if(x<1 || y<1 || x>n || y>m) return;
    
        if(fx==1){
            a[x][y]=p;
            q.push((node){x,y,p});
            dfs(1,(node){x-1,y,p});
        }
        if(fx==2){
            a[x][y]=p;
            q.push((node){x,y,p});
            dfs(2,(node){x+1,y,p});
        }
        if(fx==3){
            a[x][y]=p;
            q.push((node){x,y,p});
            dfs(3,(node){x,y-1,p});
        }
        if(fx==4){
            a[x][y]=p;
            q.push((node){x,y,p});
            dfs(4,(node){x,y+1,p});
        }
    }
    
    void bfs(){
        while(!q.empty()){
            node u=q.front(),v=q.front();
            q.pop();
            u.num++;
            v=u; v.x=u.x-1;//上 
            dfs(1,v);
            v=u; v.x=u.x+1;//下 
            dfs(2,v);
            v=u; v.y=u.y-1;//左 
            dfs(3,v);
            v=u; v.y=u.y+1;//右 
            dfs(4,v);
        }
    }
    int main(){
        cin>>m>>n;
        char zwh;
        memset(a,inf,sizeof(a));
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) a[i][j]=inf-1;
        //如果地图范围全部是比答案小的数字(比如0),那么在dfs染色的时候就会直接返回,导致错误。
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf(" %c",&zwh);
                if(zwh=='C'){
                    if(s.x) t.x=i,t.y=j,t.num=0;//找到起点和终点
                    else s.x=i,s.y=j,s.num=0;
                }
                if(zwh=='*'){
                    a[i][j]=inf;
                }
                
            }
        }
        q.push(s);
        bfs();
        cout<<a[t.x][t.y]-1;//注意减一
        return 0;
    }
    
    
    • 1

    信息

    ID
    2002
    时间
    1000ms
    内存
    128MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者