圆环中的最大总和

时间:2016-11-08 10:56:18

标签: algorithm matrix dynamic-programming onlinejudge

我正在尝试解决以下关于uva在线评判的动态编程问题:

  

水平和垂直包裹的网格称为圆环。   给定每个单元格包含整数的圆环,确定   总和最大的子矩形。子矩形的总和是   该矩形中所有元素的总和。下面的网格显示了一个   最大子矩形被遮挡的圆环。

Image of a torus

我们知道存在一个非常相似和更简单的问题:网格canot包裹的最大子矩形问题。对于更简单的变体,我们可以首先获取每行的累积,然后在2个for循环中应用kadane的算法来解决问题。对于这个问题,这是不可能的,因为网格现在可以环绕。

我已经通过将矩阵镜像4次以模拟矩阵的旋转来解决这个问题。但是,对于所有与动态编程相关的问题,我们必须制定递归关系。我不知道如何制定这个问题的重现。有人可以告诉我吗?

编辑:

我尝试使用修改过的kadane算法来搜索至少大小为1的最大矩形。但是,我仍然没有得到正确答案。作为参考,我的代码如下:

#include <cstdio>
#include <algorithm>
#include <list>
using namespace std;

int main() {
    int cc,r,c,R,C,INF = 9999;
    scanf("%d",&cc);
    while(cc--) {
        scanf("%d",&r);
        c = r;
        R = C = 2 * r;
        int l[r][c], sum[R+1][C];
        fill_n(sum[0],C,0);

        for(int i = 0; i < r; i++) {
            for(int j = 0; j < c; j++) {
                scanf("%d",&l[i][j]);
                sum[i+1][j] = l[i][j];
                sum[i+1][c+j] = l[i][j];
                sum[r+i+1][j] = l[i][j];
                sum[r+i+1][c+j] = l[i][j];
            }
        }
        for(int i = 0; i < C; i++) {
            for(int j = 1; j < R+1; j++) {
                sum[j][i] += sum[j-1][i];
            }
        }
        int g_max = -INF;
        for(int i = 0; i < r; i++) {
            for(int j = i+1; j < i+r+1; j++) {
                int t_max = sum[j][0]-sum[i][0], s = sum[j][0]-sum[i][0], L = 1, lo = 0, hi = 0;
                g_max = max(g_max,t_max);
                for(int k = L; k < C; k++) {
                    s += (sum[j][k]-sum[i][k])-(sum[j][k-L]-sum[i][k-L]);
                    t_max = max(t_max+(sum[j][k]-sum[i][k]),s);
                    if(t_max > g_max) {
                        g_max = t_max;
                        lo = k - L - 1;
                        hi = k;
                        if(hi - lo == c-1) break;
                    }
                }
            }
        }
        printf("%d\n",g_max);
    }
    return 0;
}

考虑到这个测试用例:

1
5
1 -1 0 0 -4
2 3 -2 -3 2
4 1 -1 5 0
3 -2 1 -3 2
-3 2 4 1 -4

测试用例中的网格如上所示。答案应该是15.但我得到24.我不确定我的算法有什么问题,因为我从另一个stackoverflow答案中实现了kadane的算法。有人能帮助我吗?

1 个答案:

答案 0 :(得分:0)

这是对“最大2D范围总和”问题的修改,在该问题中,我们得到了一个矩阵,其中的单元格填充有整数。我们必须找到矩阵子矩形的最大可能和。这可以在public async Task<List<Trackers>> GetTrackersDataAsync() { try { var query = client.CreateDocumentQuery<Trackers>(collectionLink, new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true }) .OrderByDescending(x => x.LocatedAt) .AsDocumentQuery(); MFZTrackers = new List<Trackers>(); while (query.HasMoreResults) { var result = await query.ExecuteNextAsync<Trackers>(); MFZTrackers.AddRange(result); } } catch (Exception e) { Console.Error.WriteLine(@"ERROR {0}", e.Message); return null; } return MFZTrackers; } 时间完成。

在这里,我们可以通过在右,下和右下角制作一个将矩阵与其自身相连的矩阵来模拟圆环面。这将创建一个O(n^4)矩阵,现在可以将其作为“最大2D范围和”问题的标准输入矩阵,但要注意的是,开始的行和列不能超出原始矩阵,并且结束的行和列之间的相差最多为2N x 2N行/列。

代码:

N