133题 农田灌溉最大化作物产量问题 | 豆包MarsCode AI刷题

107 阅读3分钟

问题描述

小M负责管理一块农田,他需要通过修建两条灌溉渠道来提升作物的总产量。农田可以表示为一个nm列的二维数组cropField,其中cropField[i][j]代表第i行第j列的作物产量。小M的灌溉方案是:

  • 一条渠道从上到下灌溉整行,另一条渠道从左到右灌溉整列。
  • 被灌溉的行或列上的作物产量会加倍(即对应位置的作物产量变为原来的两倍)。
  • 只能给每个作物位置加倍一次,即同一位置不能同时被两条渠道灌溉。

你需要帮小M找出哪一行和哪一列应该被灌溉,使得作物的总产量最大化。

解题思路

这是一个较为典型的可以用动态规划来解决的问题。我们首先计算出每一个行列的和以待备用,这里就要说一下了,AI刷题中无法使用numpy,只有标准库,不然能使用numpy的话这里会更简单计算。

如果可以的话,引入numpy

import numpy as np

只要执行以下语句就可以完成计算并返回结果

# 计算初始总产量 
total = np.sum(cropField) 
# 计算每一行的和 
row_sum = np.sum(cropField, axis=1) 
# 计算每一列的和
col_sum = np.sum(cropField, axis=0) 

不过网页中的AI刷题并不支持安装第三方库,所以需要我们自己计算实现。

然后是关于动态规划的转移方程,对于每一个dp[i][j],我们所要的是dp[i-1][j]dp[i][j-1]和他本身 sum_row[i]+sum_col[j]-cropField[i][j]的最大值就是所求。因为对dp[i][j]来说,dp[i-1][j][i- 1]*[j]数组灌溉后的最大值,dp[i][j-1][i]*[j-1]数组灌溉后的最大值,加上他本身进行比较所求就是[i]*[j]的灌溉最大值,而对第一行和第一列需要特别计算一下,因为它们没有上一行或前一列。

以下是用实现这一方法的代码:

def solution(m: int, n: int, cropField: list) -> int:
	# write code here
    sum_row=[]
    for i in range(n):
        sum_=0
        for j in range(m):
            sum_+=cropField[i][j]
        sum_row.append(sum_)
    
    sum_col=[]
    for j in range(m):
        sum_=0
        for i in range(n):
            sum_+=cropField[i][j]
        sum_col.append(sum_)
    dp=[[0 for j in range(m)] for i in range(n)]

    for i in range(n):
        for j in range(m):
            if i==0 and j==0:
                dp[i][j]=sum_row[i]+sum_col[j]-cropField[i][j]
            elif i ==0:
                dp[i][j]=max(dp[i][j-1],sum_row[i]+sum_col[j]-cropField[i][j])
            elif j==0:
                dp[i][j]=max(dp[i-1][j],sum_row[i]+sum_col[j]-cropField[i][j])
            else:
                dp[i][j]=max(dp[i-1][j],dp[i][j-1],sum_row[i]+sum_col[j]-cropField[i][j])
    total=0
    for i in range(n):
        total+=sum_row[i]
    return dp[n-1][m-1]+total

复杂度分析

时间复杂度:初始化 sum_row 和 sum_col 的时间复杂度都是 O(n×m)。动态规划填充 dp 数组的时间复杂度是 O(n×m)。计算总和 total 的时间复杂度是 O(n)。 因此,整体时间复杂度是 O(n×m)

空间复杂度:使用了 dp[n][m] 和辅助数组(sum_rowsum_col),空间复杂度是 O(n * m)

总结

动态规划其实实现也不难,主要是要明确动态转移函数是什么。有了转移函数很快就可以完成解答。