## 题目 1432: [蓝桥杯][2013年第四届真题]剪格子

时间限制: 1Sec 内存限制: 128MB 提交: 2448 解决: 858

**题目描述**
历届试题  剪格子 
时间限制：1.0s     内存限制：256.0MB
    
**问题描述**
如下图所示，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。

**输出**

> 输出一个整数，表示在所有解中，包含左上角的分割区可能包含的最小的格子数目。

**样例输入**

```python
3 3
10 1 52
20 30 1
1 2 3
```

**样例输出**

```python
3
```

### 思路一


```
def main():
    m,n=map(int,input().strip().split())
    map_=[]
    for i in range(n):
        map_.append(list(map(int,input().strip().split())))
    all_sum=0
    for i in range(n):
        for j in range(m):
            all_sum+=map_[i][j]
    if all_sum%2!=0:
        print(0)
        return 
    visited=set()
    temp_sum=0
    res=[]
    temp=[]
    def helper(visited,row,col,temp_sum,temp):
        '''
        visited:记录已经遍历过的点
        row:当前横坐标
        col:当前纵坐标
        temp_sum:已经遍历过的点的值的和
        temp:储存了当前遍历的点的坐标
        '''
        if temp_sum==all_sum/2:
            res.append(temp)
            return 
        if temp_sum>all_sum/2:
            return 
        if (row-1,col) not in visited and 0<=(row-1)<n and 0<=(col)<m:
            helper(visited|{(row-1,col)},row-1,col,temp_sum+map_[row-1][col],temp+[(row-1,col)])
        if (row+1,col) not in visited and 0<=(row+1)<n and 0<=(col)<m:
            helper(visited|{(row+1,col)},row+1,col,temp_sum+map_[row+1][col],temp+[(row+1,col)])
        if (row,col-1) not in visited and 0<=(row)<n and 0<=(col-1)<m:
            helper(visited|{(row,col-1)},row,col-1,temp_sum+map_[row][col-1],temp+[(row,col-1)])
        if (row,col+1) not in visited and 0<=(row)<n and 0<=(col+1)<m:
            helper(visited|{(row,col+1)},row,col+1,temp_sum+map_[row][col+1],temp+[(row,col+1)])
#     print(map_)
#     print(map_[0][0])
    helper(visited|{(0,0)},0,0,temp_sum+map_[0][0],temp+[(0,0)])
    if not res:
        print(0)
        return 
    else:
        print(len(min(res,key=len)))
        return
main()

```

    3 3
    10 1 52
    20 30 1
    1 2 3
    [[10, 1, 52], [20, 30, 1], [1, 2, 3]]
    10
    3


#### 思路
- 从（0，0）这个点向四周遍历找到值等于总数字和一半的组合就记录到res中，最后从res中选出长度最小即包含的最小的格子数目。


```
def dfs(pair,num_now,sum_now):
    global ret
    global vis
    if sum_now ==total//2 and num_now < ret:
        ret = num_now
    for i in dirc:
        dx = pair[0] + i[0]
        dy = pair[1] + i[1]
        if 0<=dx<m and 0<=dy<n and not vis[dx][dy]:
            vis[dx][dy]=True
            #print(dx,dy,num_now,sum_now)
            dfs((dx,dy),num_now+1,sum_now+lst[dx][dy])
            vis[dx][dy]=False
n,m = map(int,input().split())
lst=[]
total,ret = 0,1000
for i in range(m):
    tmp=list(map(int,input().split()))
    lst.append(tmp)
    total+=sum(tmp)
dirc=[(0,-1),(1,0),(-1,0),(0,1)]
vis=[[False for _ in range(n)]for _ in range(m)]
if total %2==1:
    print(0)
else:
    dfs((0,0),1,lst[0][0])
    print(ret) if ret!=1000 else print(0)
```


```
a={1,2,3}&{3,4,5}
len(a)
b=[]
b.append(a)
b
```




    [{3}]