历届试题 剪格子
/* 历届试题 剪格子 问题描述 如下图所示,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 */ import java.util.Scanner; import java.util.Stack; public class Main { static int m, n; static int map[][]; static int data[][]; static int sum = 0, sum1 = 0; static int visted[]; static int min = Integer.MAX_VALUE; static Stack<Integer> road = new Stack<Integer>(); public static void main(String[] args) { Scanner sc = new Scanner(System.in); m = sc.nextInt(); n = sc.nextInt(); visted = new int[m * n]; map = new int[m * n][m * n]; data = new int[n][m]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { data[i][j] = sc.nextInt(); sum1 += data[i][j]; } } sc.close(); creatMap(); dfs(0); System.out.println(min); } static void vist(int k) { int i = k / m, j = k % m; sum += data[i][j]; visted[k] = 1; road.push(k); } static void huisu(int k) { int i = k / m, j = k % m; sum -= data[i][j]; visted[k] = 0; road.pop(); } static boolean check() { int a[] = new int[m * n]; for (int i = 0; i < a.length; i++) a[i] = visted[i]; for (int i = 0; i < a.length; i++) if (a[i] == 0) { ddd(i, a); break; } if (flag) return true; return false; } static boolean flag = false; static boolean ddd_check(int a[]) { for (int i : a) if (i == 0) { return false; } return true; } static void ddd(int k, int a[]) { a[k] = 1; if (ddd_check(a)) flag = true; for (int i = 0; i < m * n; i++) { if (map[k][i] == 1 && a[i] == 0) { ddd(i, a); } } } static void dfs(int k) { vist(k); if (sum == sum1 / 2 && check()) { if (min > road.size()) min = road.size(); } for (int i = 0; i < m * n; i++) { if (map[k][i] == 1 && visted[i] == 0) { dfs(i); huisu(i); } } } static void creatMap() { for (int i = 0; i < m * n; i++) { if (i - 1 >= 0 && i % m != 0) liantong(i, i - 1); if (i + 1 < m * n && (i + 1) % m != 0) liantong(i, i + 1); if (i + m < m * n) liantong(i, i + m); if (i - m >= 0) liantong(i, i - m); } } static void liantong(int i, int j) { map[i][j] = 1; map[j][i] = 1; } }