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

题目 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。

输出

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

样例输入

3 3
10 1 52
20 30 1
1 2 3

样例输出

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()

思路
  • 从(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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值