/*
历届试题 剪格子
问题描述
如下图所示,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;
}
}