1 条题解

  • 0
    @ 2025-8-24 21:41:47

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Jameswood
    吾辈踯躅不前,无畏前路坎坷,无问同行无人,但忧道中花未央

    搬运于2025-08-24 21:41:47,当前版本为作者最后更新于2018-07-25 14:24:39,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    原题链接

    不知道自己怎么错的看过来,这有六种错法

    难度:普及-(但是要小心,多坑)


    较为普通的 DFS ,输入时记录初始点,将开始的 mouse(鼠标)数量设为 6,直接开始递归。但要注意以下几点:

    1. “ 一旦小H的 血量降到 0, 他将死去 ”,也就是说当小 H 血量为 1,且本格不能补充,就已经可以视为死亡了。我的做法是在每次递归开始时判断,如果鼠标数量为 0 就直接返回。

    2. “ 他可以沿路通过拾取鼠标(什么鬼。。。)来补满血量 ” 即每次遇到可以拾取鼠标的点后鼠标数量回到 6。

    3. 本题是求最小值的 DFS 算法,所以并没有明确的结束标记,我的做法是将 m*n 即所有点的数量设为上线。

    记我的失败之路(无特殊说明错误均为 wrong answer):


    1. 在移动后进行边界判断时,将 m 和 n 搞反

      • 得分 40 可以通过测试点 1 、3 、4 、7(5 、8 TLE )。失败样例一
    2. 在遇到可以拾取鼠标的点后,先将血量回复到 6 。

    3. 将步数上界设置得过小,比如 m*n/2 。

      • 得分 50 可以通过测试点 1 、2 、3 、7 、10 。失败样例三
    4. 没有设置步数上界

      • 得分 40 可以通过测试点 1 、2 、4、 7 ( 其余 MLE 错误 )。失败样例四
    5. 在超出步数上界后将回答设为 -1 。

    6. ans 初值过小或者捡到鼠标后只血量只加一亦或者捡到鼠标后血量恢复到5。

    代码实现:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    void dfs(int x,int y,int mou);
    long long a[11][11],dir[4][2]={1,0,-1,0,0,1,0,-1};
    //此处的 dir 数组用于计算 小H 的移动
    int tx,ty,lx,ly,n,m,mou=6,times=0,minans=1<<30;
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                cin>>a[i][j];
                if(a[i][j]==2){
                    tx=i;ty=j; 
                    //记录开始点
                }
                if(a[i][j]==3){
                    lx=i;ly=j;
                    //记录结束点
                }
            }
        dfs(tx,ty,mou);
        //开始搜索
        if(minans!=1<<30) cout<<minans<<endl;
        else cout<<-1<<endl;
        //如果此时 minans 与初值相等,则没有找到可行路径 QAQ
        return 0;
    } 
    void dfs(int x,int y,int mou){
    	if(mou==0||times>m*n||times>minans) return;
        //如果血量为0或者超出步数上界或者此时的步数已经超过了答案
    	if(a[x][y]==4) mou=6;
        if(x==lx&&y==ly) minans=min(times,minans);
        else{
            for(int i=0;i<4;i++){
                tx=x+dir[i][0];
                ty=y+dir[i][1];
                if(tx<=0||tx>n||ty<=0||ty>m||a[tx][ty]==0) continue;
                //边界判断和是否撞墙
                ++times;
                dfs(tx,ty,mou-1);
    			--times;
            }
        }
    }
    

    测试详情


    看在我这么多次出错,又把它们都好好总结的份上,不通过,不点赞你对的起你的良心吗……(写完题解的作者已泪崩)你们看我这么可耐,就别欺负我了

    此处应该有一张头像,但是没有加载

    记这万红之中的一抹亮色

    • 1

    信息

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