首页 > 代码库 > 算法笔记_196:历届试题 剪格子(Java)

算法笔记_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");
    }
}

 

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