算法笔记_196:历届试题 剪格子(Java)

目录

1 问题描述

2 解决方案

 


1 问题描述

问题描述

如下图所示,3 x 3 的格子中填写了一些整数。

+--*--+--+
|10* 1|52|
+--****--+
|20|30* 1|
*******--+
| 1| 2| 3|
+--+--+--+

我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60。

本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。

如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。

如果无法分割,则输出 0。

输入格式

程序先读入两个整数 m n 用空格分割 (m,n<10)。

表示表格的宽度和高度。

接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000。

输出格式

输出一个整数,表示在所有解中,包含左上角的分割区可能包含的最小的格子数目。

样例输入1

3 3
10 1 52
20 30 1
1 2 3

样例输出1

3

样例输入2

4 3
1 1 1 1
1 30 80 2
1 1 1 100

样例输出2

10


2 解决方案

具体代码如下:

import java.util.Scanner;

public class Main {
    public static int n, m;
    public static int SUM;
    public static int[][] step = {{-1,0},{1,0},{0,-1},{0,1}};
    public static int[][] map;
    public static int[][] visited;
    public static int result = 10000;

    public void testDFS(int x, int y, int[][] v) {  //完成剪切后的另一部分是否是连通的
        v[x][y] = 2;
        for(int i = 0;i < 4;i++) {
            int x1 = x + step[i][0];
            int y1 = y + step[i][1];
            if(x1 < 0 || x1 >= n || y1 < 0 || y1 >= m)
                continue;
            if(v[x1][y1] == 0)
                testDFS(x1, y1, v);
        }
    }

    public void dfs(int startX, int startY, int count, int sum) {
        if(sum == SUM / 2) {
            int x = 0, y = 0, step = 0;
            int[][] v = new int[n][m];
            for(int i = 0;i < n;i++) {
                for(int j = 0;j < m;j++) {
                    if(visited[i][j] == 0) {
                        x = i;
                        y = j;
                    }
                    v[i][j] = visited[i][j];
                }
            }
            testDFS(x, y, v);
            for(int i = 0;i < n;i++)
                for(int j = 0;j < m;j++)
                    if(v[i][j] == 2)
                        step++;
            if(step + count == n * m) {
                if(visited[0][0] == 1)
                    result = Math.min(result, count);
                else {
                    result = Math.min(result, step);
                }
            }
            return;
        } else if(sum > SUM / 2)
            return;
        for(int i = 0;i < 4;i++) {
            int x1 = startX + step[i][0];
            int y1 = startY + step[i][1];
            if(x1 < 0 || x1 >= n || y1 < 0 || y1 >= m)
                continue;
            if(visited[x1][y1] == 1)
                continue;
            visited[x1][y1] = 1;
            count++;
            sum += map[x1][y1];
            dfs(x1, y1, count, sum);
            sum -= map[x1][y1];
            count--;
            visited[x1][y1] = 0;
        }
    }

    public static void main(String[] args) {
        Main test = new Main();
        Scanner in = new Scanner(System.in);
        m = in.nextInt();
        n = in.nextInt();
        map = new int[n][m];
        SUM = 0;
        for(int i = 0;i < n;i++) {
            for(int j = 0;j < m;j++) {
                map[i][j] = in.nextInt();
                SUM += map[i][j];
            }
        }
        if(SUM % 2 == 0) {
            for(int i = 0;i < n;i++) {
                for(int j = 0;j < m;j++) {
                    visited = new int[n][m];
                    int sum = map[i][j];
                    int count = 1;
                    visited[i][j] = 1;
                    test.dfs(i, j, count, sum);
                }
            }
            if(result != 10000)
                System.out.println(result);
            else
                System.out.println("-1");
        } else
            System.out.println("-1");
    }
}
时间: 2024-11-02 23:35:19

算法笔记_196:历届试题 剪格子(Java)的相关文章

算法笔记_183:历届试题 九宫重排(Java)

目录 1 问题描述 2 解决方案   1 问题描述 问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成第二个图所示的局面. 我们把第一个图的局面记为:12345678. 把第二个图的局面记为:123.46758 显然是按从上到下,从左到右的顺序记录数字,空格记为句点. 本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达.如果无论多少步都无法到达,则输出-1. 输入格式 输入第一行包含

算法笔记_170:历届试题 分糖果(Java)

目录 1 问题描述 2 解决方案   1 问题描述 问题描述 有n个小朋友围坐成一圈.老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏: 每个小朋友都把自己的糖果分一半给左手边的孩子. 一轮分糖后,拥有奇数颗糖的孩子由老师补给1个糖果,从而变成偶数. 反复进行这个游戏,直到所有小朋友的糖果数都相同为止. 你的任务是预测在已知的初始糖果情形下,老师一共需要补发多少个糖果. 输入格式 程序首先读入一个整数N(2<N<100),表示小朋友的人数. 接着是一行用空格分开的N个偶数(每个偶数不大于1

算法笔记_187:历届试题 网络寻路(Java)

目录 1 问题描述 2 解决方案   1 问题描述 问题描述 X 国的一个网络使用若干条线路连接若干个节点.节点间的通信是双向的.某重要数据包,为了安全起见,必须恰好被转发两次到达目的地.该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径. 源地址和目标地址可以相同,但中间节点必须不同. 如下图所示的网络. 1 -> 2 -> 3 -> 1 是允许的 1 -> 2 -> 1 -> 2 或者 1 -> 2 -> 3 -> 2 都是

算法笔记_194:历届试题 翻硬币(Java)

目录 1 问题描述 2 解决方案   1 问题描述 问题描述 小明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情形是:**oo***oooo 如果同时翻转左边的两个硬币,则变为:oooo***oooo 现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢? 我们约定:把翻动相邻的两个硬币叫做一步操作,那么要求: 输入格式 两行等

【蓝桥杯】历届试题 剪格子(未完成)

  历届试题 剪格子   时间限制:1.0s   内存限制:256.0MB 问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+|10* 1|52|+--****--+|20|30* 1|*******--+| 1| 2| 3|+--+--+--+ 我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60. 本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等. 如果存在多种解答,请输出包含左上角格

蓝桥杯 历届试题 剪格子 简单的DFS~~注意输入有陷阱~~

历届试题 剪格子 时间限制:1.0s   内存限制:256.0MB 问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+ |10* 1|52| +--****--+ |20|30* 1| *******--+ | 1| 2| 3| +--+--+--+ 我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60. 本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等. 如果存在多种解答,请输出包含左上

蓝桥杯 历届试题 剪格子

历届试题 剪格子 时间限制:1.0s   内存限制:256.0MB 问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+|10* 1|52|+--****--+|20|30* 1|*******--+| 1| 2| 3|+--+--+--+ 我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60. 本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等. 如果存在多种解答,请输出包含左上角格子的那个

算法笔记_189:历届试题 横向打印二叉树(Java)

目录 1 问题描述 2 解决方案   1 问题描述 问题描述 二叉树可以用于排序.其原理很简单:对于一个排序二叉树添加新节点时,先与根节点比较,若小则交给左子树继续处理,否则交给右子树. 当遇到空子树时,则把该节点放入那个位置. 比如,10 8 5 7 12 4 的输入顺序,应该建成二叉树如下图所示,其中.表示空白. ...|-1210-|...|-8-|.......|...|-7.......|-5-|...........|-4 本题目要求:根据已知的数字,建立排序二叉树,并在标准输出中横

算法笔记_184:历届试题 约数倍数选卡片(Java)

目录 1 问题描述 2 解决方案   1 问题描述 问题描述 闲暇时,福尔摩斯和华生玩一个游戏: 在N张卡片上写有N个整数.两人轮流拿走一张卡片.要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数.例如,某次福尔摩斯拿走的卡片上写着数字"6",则接下来华生可以拿的数字包括: 1,2,3, 6,12,18,24 .... 当轮到某一方拿卡片时,没有满足要求的卡片可选,则该方为输方. 请你利用计算机的优势计算一下,在已知所有卡片上的数字和可选哪些数字的条件下,怎样选择才能保证必胜! 当