1 条题解

  • 0
    @ 2025-8-24 22:23:14

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 苏黎世
    嗯,会好的,会回来的。

    搬运于2025-08-24 22:23:14,当前版本为作者最后更新于2020-10-31 09:59:50,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    这个题确实不太简单,因为在二分的时候dfs和check的次数惊人。

    这个题如果你做出来了,那么说明你的dfs和二分答案已经炉火纯青了。

    所以,如果你是想了一会不会写来看题解,希望你看到这里再回去想想,毕竟这个题对你我觉得会很有启发吧。(等下,先把点赞留下啊喂!)

    算法:DFS+二分答案+暴力枚举

    我们可以二分从1到当前的的高度。

    需要一个方向数组。

    还有就是,不要被32MB给吓到,放心去定义吧。

    具体看代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define rint register int//稍微快一点
    const int maxn = 55;
    int n, h[maxn][maxn], ji, s, t, ans = 214748364, now;
    bool v1[maxn][maxn], v2[maxn][maxn];
    //v1存是否是村庄,v2存是否遍历
    int d[10][2] = {{0, 0},{1,0}, {0,1}, {-1, 0}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
    
    void dfs(int x, int y, int q, int z)
    {
        if (x < 1||x > n|| y < 1 || y > n||v2[x][y]||h[x][y] < q||h[x][y] > z)
          return ;//看看能不能走
        v2[x][y] = 1;
        now += v1[x][y];//若有村加1,没有就加0
        for(rint i = 1;i <= 8; ++i)
          dfs(x + d[i][0], y + d[i][1], q, z);
    }
    
    bool check(int mid, int q)
    {
    	memset(v2, 0, sizeof(v2));//每次都要把v2清空
    	
    	now = 0;
    	dfs(s, t, mid, q);
    	
    	return now == ji;//看看所有的村庄是否都被遍历过
    }
    
    void cini()
    {
        cin >> n;
        for(rint i = 1;i <= n; ++i)
            for(rint j = 1;j <= n; ++j)
            {
                char c;
                cin >> c;
                if(c == 'K')
                {
                    ++ji;//村庄数量
                    v1[i][j] = 1;
                }
                else if(c == 'P')
                  s = i, t = j;//起点
            }
        
        for(rint i = 1;i <= n; ++i)
          for(rint j = 1;j <= n; ++j)
              cin >> h[i][j];
    }
    
    void work()
    {
        int l, r, mid;
        for(rint i = 1;i <= n; ++i)
          for(rint j = 1;j <= n; ++j)
          {
            if(h[i][j] < h[s][t])
              continue;//我们只要比起点高的村
            l = 1; r = h[i][j];
            while(l <= r)
            {
                mid = (l + r) >> 1;
                if(check(mid, h[i][j]))
                {
                    ans = min(ans, h[i][j] - mid);
                    l = mid + 1;
                }else r= mid - 1;
            }
          }
        printf("%d", ans);
    }
    
    int main()
    {
        cini();
        work();//这样看起来是否会简洁一点呢
        return 0;
    }
    
    • 1

    信息

    ID
    5712
    时间
    4000ms
    内存
    32MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者