AcWing1206.剪格子——学习笔记(未AC)

news2024/9/24 8:30:08

题目:1206. 剪格子 - AcWing题库icon-default.png?t=MBR7https://www.acwing.com/problem/content/description/1208/


import java.util.Scanner;

public class Main {
    public static void main(String args[]){
        //读数据
        Scanner input = new Scanner(System.in);
        String MN = input.nextLine();
        String[] mn = MN.split(" ");
        int m = Integer.valueOf(mn[0]);
        int n = Integer.valueOf(mn[1]);
        int[][] map = new int[n][m];
        int sum = 0;
        int[] ans = {Integer.MAX_VALUE};
        for(int i = 0; i < n; i++){
            String strNum = input.nextLine();
            String[] strTemp = strNum.split(" ");
            for(int j = 0; j < m; j++){
                map[i][j] = Integer.valueOf(strTemp[j]);
                sum += map[i][j];
            }
        }


        //特殊情况:总值不能被平分
        if(sum % 2 != 0){
            System.out.println(0);
            return;
        }
        boolean[][] isRead = new boolean[n][m];//默认值是false
        isRead[0][0] = true;
        boolean[] flag = {false};
        int[][] direction = {{-1,0},{1,0},{0,-1},{0,1}};//上、下、左、右
        dfs(0,0,1,map[0][0],sum,ans,map,direction,isRead,flag);

        if(flag[0]){
            System.out.println(ans[0]);
        }else{
            System.out.println(0);
        }
    }


    //line:行 column:列 count:当前格子个数 num:当前数值 sum:总值 ans:最小格子数 map:棋盘 direction:方向 isRead:是否已读 flag:标识
    public static void dfs(int line, int column, int count, int num, int sum, int[] ans, int[][] map, int[][] direction, boolean[][] isRead, boolean[] flag){
//        //test
        //剪枝
        if(num > sum / 2 || count > ans[0]){
            return;
        }
        //截止条件
        if(num == sum / 2 && isLink(isRead)){
            ans[0] = count;
            flag[0] = true;
            return;
        }
        //搜索
        for(int i = 0; i < 4; i++){//按上下左右的顺序进行遍历
            int tline = line + direction[i][0];
            int tcolumn = column + direction[i][1];

            if(inBounds(tline,tcolumn,map) && !isRead[tline][tcolumn]){//判断是否在界内&是否已经走过
                isRead[tline][tcolumn] = true;//标记已走

                dfs(tline,tcolumn,count + 1,num + map[tline][tcolumn],sum,ans,map,direction,isRead,flag);

                //回溯
                isRead[tline][tcolumn] = false;

            }
        }
    }

    //判断是否在界内
    public static boolean inBounds(int line, int column, int[][] map){
        if(line >= 0 && line < map.length && column >= 0 && column < map[0].length){
            return true;
        }else{
            return false;
        }
    }

    //判断是否相连
    public static boolean isLink(boolean[][] read){
        boolean[][] isRead = read;
        int lineNum = isRead.length - 1;
        int columnNum = isRead[0].length - 1;
        for(int i = 0; i < lineNum + 1; i++){
            for(int j = 0; j < columnNum + 1; j++){//遍历
                if(i ==0 && j ==0 && isRead[1][0] == isRead[0][1] && isRead[1][0] != isRead[0][0]){//左上角
                    return false;
                }else
                if(i == lineNum && j == 0 && isRead[lineNum - 1][0] == isRead[lineNum][1] && isRead[lineNum][1] != isRead[lineNum][0]){//左下角
                    return false;
                }else
                if(i == 0 && j == columnNum && isRead[0][columnNum - 1] == isRead[1][columnNum] && isRead[1][columnNum] != isRead[0][columnNum]){//左上角
                    return false;
                }else
                if(i == lineNum && j == columnNum && isRead[lineNum][columnNum - 1] == isRead[lineNum - 1][columnNum] && isRead[lineNum - 1][columnNum] != isRead[lineNum][columnNum]){//右下角
                    return false;
                }else
                if(i ==0 && j != 0 && j != columnNum){//上边
                    if(isRead[0][j - 1] == isRead[1][j] == isRead[0][j + 1] && isRead[0][j + 1] != isRead[i][j]){
                        return false;
                    }
                }else
                if(j == 0 && i != 0 && i != lineNum){//左边
                    if (isRead[i - 1][0] == isRead[i+1][0] == isRead[i][1] && isRead[i][1] != isRead[i][j]){
                        return false;
                    }
                }else
                if(i == lineNum && j !=0 && j != columnNum){//下边
                    if (isRead[lineNum][j - 1] == isRead[lineNum - 1][j] == isRead[lineNum][j + 1] && isRead[lineNum][j + 1] != isRead[i][j]){
                        return false;
                    }
                }else
                if (j == columnNum && i != 0 && i != lineNum){//右边
                    if(isRead[i - 1][columnNum] == isRead[i][columnNum - 1] == isRead[i + 1][columnNum]){
                        return false;
                    }
                }else if(i != 0 && i !=lineNum && j !=0 && j != columnNum){//剩余的
                    if(isRead[i - 1][j] == isRead[i + 1][j] == isRead[i][j - 1] == isRead[i][j + 1] && isRead[i][j + 1] != isRead[i][j]){
                        return false;
                    }
                    return true;
                }
            }
        }

        return false;
    }

}

 


思路:先按规定录入数据,若总值平分后不是整数则不满题意可以直接返回“0”,否则使用深度优先搜索,计算包含左上角的分割区可能包含的最小的格子数目。

一、读取数据&特殊情况

        //读数据
        Scanner input = new Scanner(System.in);
        String MN = input.nextLine();
        String[] mn = MN.split(" ");
        int m = Integer.valueOf(mn[0]);
        int n = Integer.valueOf(mn[1]);
        int[][] map = new int[n][m];
        int sum = 0;
        int[] ans = {Integer.MAX_VALUE};
        for(int i = 0; i < n; i++){
            String strNum = input.nextLine();
            String[] strTemp = strNum.split(" ");
            for(int j = 0; j < m; j++){
                map[i][j] = Integer.valueOf(strTemp[j]);
                sum += map[i][j];
            }
        }

按照题目要求,读取数据,将int类型的数据存放在二维int数组map中。计算所有格子的值的总和sum。

//特殊情况:总值不能被平分
        if(sum % 2 != 0){
            System.out.println(0);
            return;
        }

当总值不能被2整除时,则意味着这个例子不可能被分成累加值相同的两部分,所以可以直接输出0并结束程序。

二、深度优先搜索准备工作

boolean[][] isRead = new boolean[n][m];//默认值是false
isRead[0][0] = true;
boolean[] flag = {false};
int[][] direction = {{-1,0},{1,0},{0,-1},{0,1}};//上、下、左、右

boolean类型的二维数组isRead,用于记录格子是否已经走过,格子的默认值为false经过时改为true,避免一个格子重复走过多遍。因为从坐上角第一个格子出发,因此手动将isRead[0][0]的值设为true。int类型的二维数组direction分别表示上下左右四个方向,这样就可以控制在map中的移动。因为无法获取java方法中的形参,因此耍了一个小伎俩,传了一个boolean数组flag[]进去,flag为是否成功找到的标识,若找到答案则flag为true,反之为false。

三、判断是否在界内的方法

    //判断是否在界内
    public static boolean inBounds(int line, int column, int[][] map){
        if(line >= 0 && line < map.length && column >= 0 && column < map[0].length){
            return true;
        }else{
            return false;
        }
    }

该方法用于判断是否越界,深度优先搜索中会使用到。map则是存放数据的二维数组,line和column则是当前的坐标,然后让当前坐标与map的对应参数进行对比。如果越界则返回false,否则返回true。

四、判断路径是否连续的方法

    //判断是否相连
    public static boolean isLink(boolean[][] read){
        boolean[][] isRead = read;
        int lineNum = isRead.length - 1;
        int columnNum = isRead[0].length - 1;
        for(int i = 0; i < lineNum + 1; i++){
            for(int j = 0; j < columnNum + 1; j++){//遍历
                if(i ==0 && j ==0 && isRead[1][0] == isRead[0][1] && isRead[1][0] != isRead[0][0]){//左上角
                    return false;
                }else
                if(i == lineNum && j == 0 && isRead[lineNum - 1][0] == isRead[lineNum][1] && isRead[lineNum][1] != isRead[lineNum][0]){//左下角
                    return false;
                }else
                if(i == 0 && j == columnNum && isRead[0][columnNum - 1] == isRead[1][columnNum] && isRead[1][columnNum] != isRead[0][columnNum]){//左上角
                    return false;
                }else
                if(i == lineNum && j == columnNum && isRead[lineNum][columnNum - 1] == isRead[lineNum - 1][columnNum] && isRead[lineNum - 1][columnNum] != isRead[lineNum][columnNum]){//右下角
                    return false;
                }else
                if(i ==0 && j != 0 && j != columnNum){//上边
                    if(isRead[0][j - 1] == isRead[1][j] == isRead[0][j + 1] && isRead[0][j + 1] != isRead[i][j]){
                        return false;
                    }
                }else
                if(j == 0 && i != 0 && i != lineNum){//左边
                    if (isRead[i - 1][0] == isRead[i+1][0] == isRead[i][1] && isRead[i][1] != isRead[i][j]){
                        return false;
                    }
                }else
                if(i == lineNum && j !=0 && j != columnNum){//下边
                    if (isRead[lineNum][j - 1] == isRead[lineNum - 1][j] == isRead[lineNum][j + 1] && isRead[lineNum][j + 1] != isRead[i][j]){
                        return false;
                    }
                }else
                if (j == columnNum && i != 0 && i != lineNum){//右边
                    if(isRead[i - 1][columnNum] == isRead[i][columnNum - 1] == isRead[i + 1][columnNum]){
                        return false;
                    }
                }else if(i != 0 && i !=lineNum && j !=0 && j != columnNum){//剩余的
                    if(isRead[i - 1][j] == isRead[i + 1][j] == isRead[i][j - 1] == isRead[i][j + 1] && isRead[i][j + 1] != isRead[i][j]){
                        return false;
                    }
                    return true;
                }
            }
        }
        return false;
    }

这个方法也是深度优先搜索中使用到的。题目要求,分为“连续的”两个区域,为了排除那些可以满足“值相同”的要求但是不满足“连续”要求的情况。不同位置的判断条件不同,因此分成三种情况分类讨论:四角、四边、中间部分。为了不改动原来的boolean数组isRead,换了个入参的名,并用临时变量的isRead接受传进来的boolean类型二维数组。遍历这个二维数组,不同的位置按照不同位置的判定规则做出判断。我的思路就是:如果出现类似于围棋“打吃”状况则是不连通的情况。可经过测试,我的思路仅能判断单个格子被分隔开的情况,无法判断下图的情况。(有没有大佬提供一个检验是否联通的方法。)

 五、深度优先搜索

 //line:行 column:列 count:当前格子个数 num:当前数值 sum:总值 ans:最小格子数 map:棋盘 direction:方向 isRead:是否已读 flag:标识
    public static void dfs(int line, int column, int count, int num, int sum, int[] ans, int[][] map, int[][] direction, boolean[][] isRead, boolean[] flag){
//        //test
        //剪枝
        if(num > sum / 2 || count > ans[0]){
            return;
        }
        //截止条件
        if(num == sum / 2 && isLink(isRead)){
            ans[0] = count;
            flag[0] = true;
            return;
        }
        //搜索
        for(int i = 0; i < 4; i++){//按上下左右的顺序进行遍历
            int tline = line + direction[i][0];
            int tcolumn = column + direction[i][1];

            if(inBounds(tline,tcolumn,map) && !isRead[tline][tcolumn]){//判断是否在界内&是否已经走过
                isRead[tline][tcolumn] = true;//标记已走

                dfs(tline,tcolumn,count + 1,num + map[tline][tcolumn],sum,ans,map,direction,isRead,flag);

                //回溯
                isRead[tline][tcolumn] = false;

            }
        }
    }

每一个格子都可以按照上下左右的移动顺序进行路径的选择。当前累加值刚好为总值的一半时,且两部分联通,即为查找成功。若某一路径查找不成功说明当前选择不合适,则进行回溯,回溯意为“退回”上一步,进行下个选择。移动时需要用到“三”中提到的判断是否在界内的方法,再得到结果时,需要用“四”中提到的判断是否联通的方法。(因为我的该方法仍有bug,所以导致不能Ac)

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

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

相关文章

Apache ShardingSphere分表的简单使用和常见问题

目录 简介 什么是 Apache ShardingSphere? 分库分表的背景 使用 pom 配置 1&#xff0c;application.properties配置文件 2&#xff0c;创建配置类 分表 验证分表 常见问题 自定义分表规则未生效 简介 官网&#xff1a;Apache ShardingSphere 版本&#xff1a;4…

ArcGIS基础实验操作100例--实验42创建渔网Fishnet

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验42 创建渔网Fishnet 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&a…

深度学习推理框架调研总结

深度学习推理框架1.移动端深度学习推理框架调研1.1 小米的MACE&#xff08;2017&#xff09;1.2 阿里的MNN1.3 腾讯的TNN1.4 ARM的tengine1.5 百度的paddle-mobie1.6 Facebook的Caffe2&#xff08;*&#xff09;1.7 Google的TensorFlow Lite &#xff08;*&#xff09;1.8 Appl…

南京晓庄操作系统期末复习【背诵部分】

操作系统期末复习背诵部分第一章1.操作系统的特征&#xff1a;2.操作系统的最基本特征是什么&#xff0c;为什么3.操作系统的目标4.操作系统的主要功能5.计算机资源6.多道程序设计时应解决什么问题7.三种操作系统及特点第二章1.进程的定义2.进程的特征3.进程的三种基本状态4.进…

Spark04: Transformation与Action开发

一、创建RDD的三种方式 RDD是Spark编程的核心&#xff0c;在进行Spark编程时&#xff0c;首要任务是创建一个初始的RDD这样就相当于设置了Spark应用程序的输入源数据然后在创建了初始的RDD之后&#xff0c;才可以通过Spark 提供的一些高阶函数&#xff0c;对这个RDD进行操作&a…

python学生管理系统(pyqt5 含界面)

学生管理系统项目流程 项目模块 账号登陆 人脸识别 增添学生信息 删除学生信息 改动学生信息 查询学生信息 项目主体框架 app.py为主代码&#xff0c;负责用于界面打开展示。img文件夹负责放置项目qrc的图像page文件夹为单独页面的类plugin文件夹为功能模块的类ui文件夹…

机器人中的数值优化|【一】数值优化基础

数值优化基础 凸集 Convex Sets 凸集的定义 令X是线性空间。如果对于X的子集S中的所有x和y&#xff0c;并且在区间 [0,1]中的所有t&#xff0c;点 (1−t)xty(1-t)x ty(1−t)xty也属于S&#xff0c;则S称为凸集。 不失一般性&#xff0c;对于所有的凸集&#xff0c;其线性组…

Zookeeper详解(二)——API 事件监听

Java API znode是zooKeeper集合的核心组件&#xff0c;zookeeper API提供了一小组方法使用zookeeper集合来操纵znode的所有细节。 客户端应该遵循以下步骤&#xff0c;与zookeeper服务器进行清晰和干净的交互。 连接到zookeeper服务器。zookeeper服务器为客户端分配会话ID。…

uniapp 之 接入小程序客服

目录 前言 小程序客服 代码只需要一步 配置也需要一步​​​​​​​ 前言 小程序客服 因老大 看到别人家有在线客服这个功能&#xff0c;就让我也做一个&#xff0c;这个功能很简单 效果图1 代码只需要一步 <button type"default" open-type"con…

MATLAB | 绘图复刻(六) | 分组环形热图

有粉丝问我Ecology Letters, (2021) 24: 1018–1028 Soil carbon persistence governed by plant input and mineral protection at regional and global scales 这篇文章中的Figure 2咋画&#xff0c;原图长这样&#xff1a; 复刻效果&#xff1a; 完整步骤 0 数据定义 按…

node.js创建网站实例1

1.node.js安装 我的电脑环境&#xff1a;win10 网址&#xff1a;https://nodejs.org/en/ 我下载了18.12.1版本 一路next默认安装&#xff0c;安装完成后&#xff0c;运行cmd&#xff0c;查看版本号 会同时安装npm&#xff0c;也可以同时查看版本号 2.创建第一个网站实例hell…

内卷对于2022是一种无奈,也是一种修行

其实我们谁也不知道2023年对于我们普通的开发人员来说会有什么样的试炼&#xff0c;因为2022年身边有太多的人&#xff0c;为了工作&#xff0c;为了生活&#xff0c;为了家庭&#xff0c;为了理想&#xff0c;不得不选择走向别人看似很卷的那条路。 对于我们周围的人来说&…

【Vim】基本操作及命令集详解

概述 Vim 是从 vi 发展出来的一个文本编辑器。vi 内置在Linux系统中&#xff0c;是vim的简化版编辑器&#xff0c;vim则需要进行安装使用。Vim代码补全、编译及错误跳转等方便编程的功能特别丰富&#xff0c;可以实现高效率移动和高效的输入&#xff0c;在程序员中被广泛使用。…

CPT203-Software Engineering(3)

文章目录9. Software Design9.1 Architecture Design9.1.1 Architectural patterns9.2 Component-level Design9.2.1 Component9.2.2 Views of component9.2.3 Component-level design process9.3 User Interface Design9.3.1 Interface Design Process9.3.2 Interface Design …

蓝桥杯Python练习题16-最大最小公倍数

资源限制   内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述   已知一个正整数N&#xff0c;问从1~N中任选出三个数&#xff0c;他们的最小公倍数最大可以为多少。 输入格式   输入一…

三维数学(一)

视频教程&#xff1a;https://www.bilibili.com/video/BV12s411g7gU?p155 向量 一个数字列表&#xff0c;表示各个维度上的有向位移&#xff1b;同时也是一个有大小有方向的物理量&#xff0c;大小及向量的模长&#xff0c;而方向即空间中向量的指向&#xff0c;可以表示物体…

TikTok Shop 越南站点收入已达Lazada 的 80%

让我们一起来看看今日都有哪些新鲜事吧&#xff01;01 TikTok Shop 越南站点收入已达Lazada 的 80% 据越南电商平台数据分析软件Metric.vn 统计&#xff0c;Shopee、Lazada、Tiki 和 Sendo 仍然主导着越南电子商务市场&#xff0c;1-11 月&#xff0c;共销售了 13 亿件产品。其…

简化开发小技巧-Mybatis-Plus的使用和常用操作

目录 简介 快速使用 pom 代码 mapper service 使用 常用操作 简单或操作查询 多条件或查询 更新字段为null 方法一&#xff0c;如果要更新的字段是String类型&#xff0c; 方法二&#xff0c; 使用mybatis-plus的字段注入。 方法三&#xff0c;使用UpdateWrapper…

基于R的Bilibili视频数据建模及分析——预处理篇

基于R的Bilibili视频数据建模及分析——预处理篇 文章目录基于R的Bilibili视频数据建模及分析——预处理篇0、写在前面1、项目介绍1.1 项目背景1.2 数据来源1.3 数据集展示2、数据预处理2.1 删除空数据2.2 增加id字段2.3 处理数值字段3、参考资料0、写在前面 实验环境 Python版…

Stable Diffusion背后原理(Latent Diffusion Models)

前言 2023年第一篇博客&#xff0c;大家新年好呀~ 这次来关注一下Stable Diffusion背后的原理&#xff0c;即 High-Resolution Image Synthesis with Latent Diffusion Models 这篇论文。 之前关注的那些工作只能工作到 256256256 \times 256256256 像素(resize成这个后才输…