《算法竞赛·快冲300题》每日一题:“连接草坪(II)”

news2025/1/6 18:57:14

算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。

文章目录

  • 题目描述
  • 题解
  • C++代码
  • Java代码
  • Python代码

连接草坪(II)” ,链接: http://oj.ecustacm.cn/problem.php?id=1868

题目描述

【题目描述】 在N×M的地图上,X表示草,.表示土地。
  一个X与上下左右的X相连形成一片草坪。
  现在已知地图上有三片草坪,最少需要将多少个单位上的土地变成草,才能把两块草坪连接成一块草坪。
【输入格式】 输入第一行为正整数N和M,不超过50。
  接下来N行,每行M个字符。
**【输出格式】**输出一个数字表示答案。
【输入样例】

6 16
................
..XXXX....XXX...
...XXXX....XX...
.XXXX......XXX..
........XXXXX...
..XXX....XXX....

【输出样例】

4

题解

   题目给出了3块互不连通的草地,问最少把多少块土地变成草,可以把3块草地连成一块草地。考虑两种情况:
  (1)从土地的角度考虑。对任意一块土地坐标(x,y),分别计算它到3块草地的3个最少土地(最短路径),然后相加,得到土地(x,y)到3块草地的总最短路径count(x,y)。在所有count(x,y)中取最小值,是否就是答案?不一定,因为这些路径可能穿过其它的草地,导致重复计算。例如样例中左上角(0,0),它到3块草地的最短路径分别是3、11、7,但是它到3块草地的总最短路径实际上是3+4+4。
  (2)从草地的角度考虑。计算任意两块草地之间的最少土地(最短路径),记为Min[],其中Min[1]是土地(1-2)之间的最短路、Min[2]是土地(2-3)之间的最短路、Min[3]是土地(1-3)之间的最短路。那么是否min(Min[1]+Min[2], Min[2]+Min[3], Min[1]+Min[3]就是答案?不一定,它可能还不如情况(1)算出的最短路。
  例如下图,根据(2)算总最短路,3块草地之间的最短路是1、3、3,总短短路min(1+3, 3+3, 1+3)=4。但是根据情况(1)算最短路,箭头指向的土地k到3个草地的距离是1、3、1,总最短路是1+3+1-2=3,这里减2,是因为k被算了3次,其实只需要算1次。
在这里插入图片描述
  根据情况(1)和(2)算出的结果,取它们的最小值,就是答案。。
【重点】 DFS的应用 。

C++代码

   代码分4步:
  1、标记每个点属于哪个连通块,用DFS编码。
  2、枚举每块土地,计算它到3个草地的最小距离,即情况(1)。
  3、计算3个草地之间的最短距离,即情况(2)。
  4、在情况(1)和情况(2)中找最小值,就是答案。
  代码的复杂度约为O(NM)。

#include<bits/stdc++.h>
using namespace std;
int n, m;
char Map[55][55];           //存图
int id[55][55],id_cnt=0;    //id[x][y]=id_cnt: 点(x,y)属于第id_cnt个草地,id_cnt=1,2,3
vector<pair<int,int>>A[4];  //A[i]: 第i个草地中有哪些点
int dir[4][2] = {1,0,0,1,-1,0,0,-1};   //上下左右四个方向
void dfs(int x, int y, int c){  //从(x,y)开始搜它的邻居草地,并标记属于c个草地
    id[x][y] = c;               //点(x,y)属于第c个草地
    A[c].push_back(make_pair(x, y));    //这样写更好: A[c].emplace_back(x, y);
    for(int i = 0; i < 4; i++){         //上下左右4个邻居
        int nx = x + dir[i][0], ny = y + dir[i][1];   //邻居坐标
        if(nx < 0 || nx >= n || ny < 0 || ny >= m)  continue;
        if(Map[nx][ny] == '.')  continue;  //土地不在草地中
        if(id[nx][ny])          continue;  //这个点已经遍历过
        dfs(nx, ny, c);                    //继续
    }
}
int Count(int x, int y, int i){         //计算(x,y)到第i个草地的最短距离
    int ans = 100;
    for(auto a : A[i])
        ans = min(ans, abs(a.first - x) + abs(a.second - y));
    return ans;
}
int main(){
    cin >> n >> m;
    for(int i = 0; i < n; i++)  cin >> Map[i];
    //1、标记每个点属于哪个连通块
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
            if(Map[i][j] == 'X' && !id[i][j])
                dfs(i, j, ++id_cnt);
    int ans = 100;                //答案
    //2、枚举每块土地,计算它到3个草地的最小距离,即情况(1)
    for(int i = 0; i < n; i++)     //任意1个土地到其它草地的最小距离
        for(int j = 0; j < m; j++)
            if(Map[i][j] == '.')  //如果(i,j)是土地,计算它到3个草地的最小距离
                ans = min(ans, Count(i,j,1) + Count(i,j,2) + Count(i,j,3) - 2);  
//为什么要 -2 ?因为把自己算了3次,其实只需要算1次
    //3、计算3个草地之间的最短距离:1-2 2-3 1-3。
    int Min[4] = {0, 100, 100, 100};  //例如Min[1]是草地1-2的最短距离
    for(int i = 1; i <= 3; i++){      //第i个草地和第j个草地的最短距离
        int j = i+1 <= 3 ? i+1 : 1;
        for(auto &a : A[i])
            Min[i] = min(Min[i], Count(a.first, a.second, j));
    }
    //4、计算连通3个草地的最短距离,找最小值,即情况(2)。并与情况(1)的结果比较。
    for(int i = 1; i <= 3; i++)
        ans = min(ans, Min[i] + Min[i+1 <= 3 ? i+1 : 1] - 2);
    cout<<ans<<endl;
    return 0;
}

Java代码

import java.util.*;
public class Main {
    static int n, m, id_cnt = 0;
    static char[][] Map = new char[55][55];
    static int[][] id = new int[55][55];
    static List<List<Pair<Integer, Integer>>> A = new ArrayList<>(4);
    static int[][] dir = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

    static void dfs(int x, int y, int c) {
        id[x][y] = c;
        A.get(c).add(new Pair<>(x, y));
        for (int i = 0; i < 4; i++) {
            int nx = x + dir[i][0], ny = y + dir[i][1];
            if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
            if (Map[nx][ny] == '.') continue;
            if (id[nx][ny] != 0) continue;
            dfs(nx, ny, c);
        }
    }

    static int Count(int x, int y, int i) {
        int ans = 100;
        for (Pair<Integer, Integer> a : A.get(i)) 
            ans = Math.min(ans, Math.abs(a.getKey() - x) + Math.abs(a.getValue() - y));
        return ans;
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        n = cin.nextInt();
        m = cin.nextInt();
        for (int i = 0; i < n; i++) 
            Map[i] = cin.next().toCharArray();
        for (int i = 0; i < 4; i++) 
            A.add(new ArrayList<>());
        for (int i = 0; i < n; i++) 
            for (int j = 0; j < m; j++)
                if (Map[i][j] == 'X' && id[i][j] == 0) 
                    dfs(i, j, ++id_cnt);
        int ans = 100;
        for (int i = 0; i < n; i++) 
            for (int j = 0; j < m; j++) 
                if (Map[i][j] == '.') 
                    ans = Math.min(ans, Count(i, j, 1) + Count(i, j, 2) + Count(i, j, 3) - 2);
        int[] Min = {0, 100, 100, 100};
        for (int i = 1; i <= 3; i++) {
            int j = i + 1 <= 3 ? i + 1 : 1;
            for (Pair<Integer, Integer> a : A.get(i)) 
                Min[i] = Math.min(Min[i], Count(a.getKey(), a.getValue(), j));
        }
        for (int i = 1; i <= 3; i++) 
            ans = Math.min(ans, Min[i] + Min[i + 1 <= 3 ? i + 1 : 1] - 2);
        System.out.println(ans);
        cin.close();
    }
    static class Pair<K, V> {
        public K key;
        public V value;
        public Pair(K key, V value) {
            this.key = key;
            this.value = value;
        }
        public K getKey() {  return key;    }

        public V getValue() {return value;  }
    }
}

Python代码

  

n, m = map(int, input().split())
Map = [input() for _ in range(n)]
id, id_cnt = [[0] * m for _ in range(n)], 0
A = [[] for _ in range(4)]
dir = [(1, 0), (0, 1), (-1, 0), (0, -1)]
def dfs(x, y, c):
    id[x][y] = c
    A[c].append((x, y))
    for i in range(4):
        nx, ny = x + dir[i][0], y + dir[i][1]
        if nx < 0 or nx >= n or ny < 0 or ny >= m: continue
        if Map[nx][ny] == '.': continue
        if id[nx][ny] != 0:    continue
        dfs(nx, ny, c)
def Count(x, y, i):
    ans = 100
    for a in A[i]:
        ans = min(ans, abs(a[0] - x) + abs(a[1] - y))
    return ans
for i in range(n):
    for j in range(m):
        if Map[i][j] == 'X' and id[i][j] == 0:
            dfs(i, j, id_cnt+1)
            id_cnt += 1
ans = 100
for i in range(n):
    for j in range(m):
        if Map[i][j] == '.':
            ans = min(ans, Count(i, j, 1) + Count(i, j, 2) + Count(i, j, 3) - 2)

Min = [0, 100, 100, 100]
for i in range(1, 4):
    j = i+1 if i+1 <= 3 else 1
    for a in A[i]:
        Min[i] = min(Min[i], Count(a[0], a[1], j))
for i in range(1, 4):
    ans = min(ans, Min[i] + Min[i+1 if i+1 <= 3 else 1] - 2)
print(ans)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/842432.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ARM64 ATF 系列 1 -- ATF 中断向量表及SMC 处理流程】

文章目录 1.1 ATF 中断向量表1.1.1 ATF 汇编宏 vector_base 1.2 ATF SMC 中断处理流程 1.1 ATF 中断向量表 ATF 中断向量表的定义位于文件&#xff1a;bl31/aarch64/runtime_exceptions.S vector_base runtime_exceptions/* -----------------------------------------------…

Spring+MyBatis整合案例

提示&#xff1a;要有自学能力&#xff0c;会学习 文章目录 前言前期准备项目内容数据库创建应用程序配置po 包代码mapper 包代码service 包代码测试类代码添加事物处理功能 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 前期准备 第一步&#xff1a…

[CSS] 图片九宫格

效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"/><meta http-equiv"X-UA-Compatible" content"IEedge"/><meta name"viewport" content"widthdevice-…

vscode自动补全(智能提示)大小写问题

最近发现vscode的自动补全有时候显示的不是想要的&#xff0c;具体表现为&#xff1a;我输入了几个字母&#xff0c;但是提示列表里面没有我需要的内容。 例如&#xff1a; 我输入了list&#xff0c;但是没有显示java.util中的List&#xff1b; 或者我输入了hashmap&#xf…

海外媒体发稿:软文写作方法方式?一篇好的软文理应合理规划?

不同种类的软文会有不同的方式&#xff0c;下面小编就来来给大家分析一下&#xff1a; 方法一、要选定文章的突破点&#xff1a; 所说突破点就是这篇文章文章软文理应以什么样的视角、什么样的见解、什么样的语言设计理念、如何文章文章的标题来写。不同种类的传播效果&#…

Apache+Tomcat 整合

目录 方式一&#xff1a;JK 1、下载安装包 2、添加依赖 3、启动服务&#xff0c;检查端口是否监听 4、提供apxs命令 5、检查是否确实依赖 6、编译安装 7、重要配置文件 方式二&#xff1a;http_proxy 方式三&#xff1a;ajp_proxy 方式一&#xff1a;JK 1、下载安装…

Vulnhub: ColddWorld: Immersion靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.183 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.183 查看login的源码发现提示&#xff1a;page和文件/var/carls.txt 漏洞利用 wfuzz探测account.php页面发现文件包含&am…

前端笔记html-layer使用

layer.open方法 layer.open({type:2, //可传入的值有&#xff1a;0&#xff08;信息框&#xff0c;默认&#xff09;1&#xff08;页面层&#xff09;2&#xff08;iframe层&#xff09;3&#xff08;加载层&#xff09;4&#xff08;tips层&#xff09;title: title,content:[…

高抗干扰LCD液晶屏驱动芯片,低功耗的特性适用于水电气表以及工控仪表类产品

VK2C23是一个点阵式存储映射的LCD驱动器&#xff0c;可支持最大224点&#xff08;56SEGx4COM&#xff09;或者最大416点&#xff08;52SEGx8COM&#xff09;的LCD屏。单片机可通过I2C接口配置显示参数和读写显示数据&#xff0c;也可通过指令进入省电模式。其高抗干扰&#xff…

怎么进行流程图制作?用这个工具制作很方便

怎么进行流程图制作&#xff1f;流程图是一种非常有用的工具&#xff0c;可以帮助我们更好地理解和展示各种复杂的业务流程和工作流程。它可以将复杂的过程简化为易于理解的图形和文本&#xff0c;使得人们更容易理解和跟踪整个流程。因此&#xff0c;制作流程图是在日常工作中…

用低代码构建高效敏捷工作流

随着行业业务发展及业务流程诉求的增长&#xff0c;企业信息资源越来越表现出一种异构分布、松散耦合的特点。实现大规模、异构、分布式执行环境&#xff0c;使得相互关联的任务能够高效运转成为了业务管理的强诉求。以事件驱动和数据驱动来进行应用系统构建也就变得更加实效。…

UE中低延时播放RTSP监控视频解决方案

第1章 方案简介 1.1 行业痛点 在各种智慧城市、智慧社区、智慧水利、智慧矿山等数字孪生项目中&#xff0c;经常使用通UE来开发三维可视化场景。在这些场景中通常都需要把现场的各种监控视频在UE的可视化场景中接入&#xff0c;主要包含海康威视、大华、宇视、华为等众多监控…

SpringBoot实现文件记录日志,日志文件自动归档和压缩

&#x1f60a; 作者&#xff1a; Eric &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_47316183?typeblog &#x1f389; 主题&#xff1a;SpringBoot实现文件记录日志&#xff0c;日志文件自动归档和压缩 ⏱️ 创作时间&#xff1a; 2023年08月06日 文章目…

[webpack] 基本配置 (一)

文章目录 1.基本介绍2.功能介绍3.简单使用3.1 文件目录和内容3.2 下载依赖3.3 启动webpack 4.基本配置4.1 五大核心概念4.2 基本使用 1.基本介绍 Webpack 是一个静态资源打包工具。它会以一个或多个文件作为打包的入口, 将我们整个项目所有文件编译组合成一个或多个文件输出出去…

ad+硬件每日学习十个知识点(23)23.8.3(LDO 设计实例)(涉及到自控没听懂,学完自控再回来看)

文章目录 1.输入电容的选取&#xff08;两个&#xff0c;一个大电容&#xff0c;一个小电容&#xff09;2.输出电容的选取&#xff08;两个&#xff0c;一个大电容&#xff0c;一个小电容&#xff09;3.有些LDO需要输出的最小负载电流&#xff0c;所以需要接一个下拉电阻。4. 1…

使用TransBigData快速高效地处理、分析、挖掘出租车GPS数据

01、TransBigData简介 TransBigData是一个为交通时空大数据处理、分析和可视化而开发的Python包。TransBigData为处理常见的交通时空大数据&#xff08;如出租车GPS数据、共享单车数据和公交车GPS数据等&#xff09;提供了快速而简洁的方法。TransBigData为交通时空大数据分析的…

JavaScript的对象+内置对象(Math+Date日期+数组+字符串)

一.创建对象 对象是由属性和方法组成的 创建对象的三种方法: 1.利用字面量创建对象 var obj{uname : 张三疯 ,age : 18 ,sex : 男 ,sayHi : function(){console.log(hi~);}} 里面的属性或者方法采用键值对的形式多个属性或者方法用逗号隔开方法冒号后面跟的是一个匿名…

第四次作业 运维高级 构建 LVS-DR 群集和配置nginx负载均衡

1、基于 CentOS 7 构建 LVS-DR 群集。 LVS-DR模式工作原理 首先&#xff0c;来自客户端计算机CIP的请求被发送到Director的VIP。然后Director使用相同的VIP目的IP地址将请求发送到集群节点或真实服务器。然后&#xff0c;集群某个节点将回复该数据包&#xff0c;并将该数据包…

如何创建51单片机KEIL工程

如何创建51单片机KEIL工程步骤&#xff1a; &#xff08;1&#xff09;打开keil软件&#xff0c;点击工具栏-Project&#xff0c;选择创建新的工程&#xff1b; &#xff08;2&#xff09;然后给工程命名&#xff0c;文章以project为例&#xff0c;然后点击保存 &#xff08…

ubuntu 暂时不能解析域名 解决办法

需要修改系统DNS 打开终端&#xff1a;输入 sudo vi /etc/resolv.conf 回车 在打开的配置文件中添加DNS信息 nameserver 114.114.114.114 nameserver 8.8.8.8 保存退出&#xff0c;重启系统即可。