import java.util.Scanner;
/*
* 将抽象的问题具体化
* 递归回溯
* 递归多个方面的缩小递归
* 因为是多个方面的因此需要判定一下是否有循环回原来方面的问题
* 回溯的作用是我现在站在这个点上张望,我张望四周之后用完了,再给你们用
*
*
* 当前数据可以取得的情况下(先标记这个位置以后别人不能用)再次递归别的数据
* 递归所有可能的情况上下左右,
* 之后进行回溯
*
* 递归当前节点考虑所有的情况(因为自己已经被标记了不会出现会还的情况)
* 之后回溯
* 图的深度优先遍历的思想:
* 找到与这个点相连的所有点
* 从一个点出发不断进入他的所有向量的店
* 进入
* 进入
* 深度进入
* 之后回溯
* 回溯
* 之后回来
* 其实就是暴力破解
*
*
*
*
*/
public class Main {
public static int num = Integer.MAX_VALUE;
public static boolean isAccess[][];
public static void f()
{
Scanner in = new Scanner(System.in);
int c = in.nextInt();
int r = in.nextInt();
int a[][] = new int[r][c];
isAccess = new boolean[r][c];
int sum = 0;
int result = 0;
for(int i = 0;i<r;i++)
{
for(int j = 0;j<c;j++)
{
a[i][j] = in.nextInt();
sum+=a[i][j];
isAccess[i][j] = true;
}
}
if(sum%2!=0)
{
System.out.println(0);
return;
}
int biSum = sum/2;//这里是一半的数据
isAccess[0][0] = false;
fun(a, 1, 0, biSum-a[0][0], r, c, 1);
fun(a, 0, 1, biSum-a[0][0], r, c, 1);
if(num!=Integer.MAX_VALUE)
{
System.out.println(num);
}
else
{
System.out.println(0);
}
}
public static void fun(int a[][],int rn,int cn,int sum,int r,int c,int cnum)
{
if(rn>=r||cn>=c||rn<0||cn<0||!isAccess[rn][cn])
return;
if(sum<0)
return;
if(cnum>=r*c)
return;
if(sum==0)
{
if(cnum<num)
{
num = cnum;
}
return;
}
if(sum-a[rn][cn]==0)
{
cnum++;
if(cnum<num)
{
num = cnum;
}
isAccess[rn][cn] = true;
}
else
{
if(sum-a[rn][cn]>0)
{
isAccess[rn][cn] = false;
int tmp = ++cnum;//多个参数传递的时候一定要注意啊
fun(a,rn+1,cn,sum-a[rn][cn],r,c,tmp);
fun(a,rn-1,cn,sum-a[rn][cn],r,c,tmp);
fun(a,rn,cn+1,sum-a[rn][cn],r,c,tmp);
fun(a,rn,cn-1,sum-a[rn][cn],r,c,tmp);
isAccess[rn][cn] = true;
}
}
}
public static void main(String[] args) {
f();
}
}
华love邵