最大子阵

题目
1.如果单纯枚举首行,末行,首列,末列来做这道题,就是四重循环,数据最大时,每重循环大概500次,500^4时间复杂度可以达到十的十次方,肯定会超时。所以要考虑能否降循环,或者找到贪心,dp规律。
2.我们思考一下,可以发现。我们可以开一个数组sum,用来记录某个格子头上全部的格子+它本身的和。举个例子,样例的数据是
-1 -4 3
3 4 -1
-5 -2 8
那么sum数组就是
-1 -4 3
2 0 2
-3 -2 10
/sum数组的建立看代码13~24行/
3.建立起sum数组之后,sum的每个元素就代表该列从第一个元素到其自身的和。比如sum数组‘0’这个格子,就是样例数组第二列从第一个元素加到这个位置的和,-4+4=0。‘10’这个格子=3+(-1)+8,其它同理
4.为什么要求这个sum数组?因为我们可以通过这个sum数组求出原数组中任意一列的任意一行元素到任意一行元素的和。比如我要求第一列中,第二行到第三行的和。
这个和=sum【3】【1】-sum【2-1】【1】
所以和=-3-(-1)=-2

仔细看,式子中的2需要减1,第三行减去第二行头上一格得到的结果就是第二行到第三行的和
5.枚举首行,末行,当前考虑的列尾。不需要四重循环。三重循环就可以一一列举各种情况了。用最大子段和的思想求出某种首行末行时,以这个元素为列尾得到的最优和。全部的最优和里面最大的就是结果。(所谓最大字段和就是前面小于0就舍弃,大于0就加上,
代码在评测系统过了50%分数,超时了

n,m=map(int,input().strip().split())
arr=[list(map(int,input().strip().split())) for _ in range(n)]
temp=[[0 for _ in range(m)] for _ in range(n+1)]
for i in range(n):
        for j in range(m):#第一行变成0
                temp[i+1][j]=arr[i][j]+temp[i][j]

ans=-5001
for i in range(0,n):#i和j来取每一列的不同行
        for j in range(i+1,n+1):
                #这里是用了最大子段的思想
                temp_sum=temp[j][0]-temp[i][0]
                for k in range(1,m):
                   num=temp[j][k]-temp[i][k]
                   temp_sum=max(temp_sum+num,num)
                   ans=max(ans,temp_sum)
print(ans)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值