问题描述:
如下图所示,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;
public class 剪格子 {
static int[][] visit;
static int min = Integer.MAX_VALUE;
static int[] dx = {-1,0,1,0}; //上,左,下,右
static int[] dy = {0,-1,0,1};
static int m;
static int n;
static int sum=0; //记录所有数的总和
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
m = scanner.nextInt(); //行
n = scanner.nextInt(); //列
visit = new int[m][n];
int[][] arr = new int[m][n];
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) {
arr[i][j] = scanner.nextInt();
sum += arr[i][j];
}
}
dfs(arr,0,0,arr[0][0]);
System.out.println(min);
}
private static void dfs(int[][] arr, int x, int y, int s) {
visit[x][y] = 1;
if(s == sum-s) {
int temp = 0;
for(int i=0; i<m; i++){
for(int j=0; j<n; j++)
temp += visit[i][j];
}
if(temp<min) min = temp;
return ;
}
for(int i=0; i<4; i++) {
int sx = x+dx[i];
int sy = y+dy[i];
if(sx>=0 && sy>=0 && sx<m && sy<n && visit[sx][sy]==0) {
visit[sx][sy] = 1;
dfs(arr, sx, sy, s+arr[sx][sy]);
visit[sx][sy] = 0; //回溯
}
}
}
}