算法笔记_196:历届试题 剪格子(Java)
目录
1 问题描述
问题描述
如下图所示,3 x 3 的格子中填写了一些整数。
+--*--+--+
|10* 1|52|
+--****--+
|20|30* 1|
*******--+
| 1| 2| 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
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
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"); } }
每天一小步,成就一大步