UVA10074 Take the Land【最大子段和+DP】

The poor man went to the King and said, “Lord, I cannot maintain my family. Please give me some wealth so that I can survive with my wife and children.” The King replied, “I shall grant you a piece of land so that you can cultivate and grow food for your family. In the southern part of the Kingdom there is a rectangular forest. Trees have been planted there at regular intervals. Some of the trees have been cut for use. You are allowed to take any rectangular piece of land that does not contain any tree. You need not go to the forest to select the piece of land. I have a map containing 1’s at places where
there is a tree and 0s at points where the tree has been cut.”
Help the poor man to find out the largest piece of land. Area of the land is measured in units of number of trees that were there. Your program should take a matrix of 1’s and 0’s as input and output the area of the largest rectangular piece of land that contain no tree. Be careful about the efficiency of your program.
Input
The input file may contain multiple test cases. The first line of each test case contains two integers M and N (1 ≤ M, N ≤ 100) giving the number of rows and columns in the matrix that follows. Each of the next M lines contains N symbols (either ‘0’ or ‘1’). Two consecutive symbols in a line will be separated by a single space. The input terminates with two zeros for M and N.
Output
For each test case in the input print a line giving the area (in terms of the number of trees were there) of the largest rectangular piece of land containing no tree.
Sample Input
6 7
0 1 1 0 1 1 0
0 0 0 0 0 1 0
1 0 0 0 0 0 1
0 1 0 0 0 0 1
1 1 0 0 0 1 0
1 1 0 1 1 0 0
0 0
Sample Output
12

问题链接UVA10074 Take the Land
问题简述:给定一个m*n的矩阵,矩阵元素只由0和1构成,找出只包含元素0的最大子矩阵。
问题分析
    这个题跟参考链接的题类似,需要修改输入输出格式,需要考虑矩阵大小构成,需要反转一下0和1。
    将值为0的元素换为1,将值为1的元素换为足够小的负数(考虑每个元素都为0即可), 进行最大子矩阵进行计算即可。因为只要有足够大的元素在子矩阵中,其子矩阵和就变成负。
    后一个解题程序时间复杂度不够好,增加2种解法。
程序说明:(略)
参考链接UVA836 Largest Submatrix【最大子段和+DP】
题记:(略)

AC的C++语言程序(前缀和+滑动窗口法)如下:

/* UVA10074 Take the Land */

#include <bits/stdc++.h>

using namespace std;

const int N = 100;
int sum[N + 1][N + 1];
const int M1000 = - (N + 1) * (N + 1);

int main()
{
    int m, n, a;
    while(~scanf("%d%d", &m, &n) && (m || n)) {
        memset(sum, 0, sizeof(sum));

        for(int i = 1; i <= m; i++) {
            sum[i][0] = 0;
            for(int j = 1; j <= n; j++) {
                scanf("%d", &a);
                a = a ? M1000 : 1;
                sum[i][j] = sum[i][j - 1] + a;
            }
        }

        // 滑动窗口法:按第i-j列,对所有的行计算最大子段和
        int maxSum = 0;
        for(int i = 1; i <= n; i++)
            for(int j = i; j <= n; j++) {
                int subSum = 0;
                for(int k = 1; k <= m; k++) {
                    subSum += sum[k][j] - sum[k][i - 1];
                    if(subSum > maxSum) maxSum = subSum;
                    if(subSum < 0) subSum = 0;
                }
            }

        printf("%d\n", maxSum);
    }

    return 0;
}

AC的C++语言程序(前缀和+DP)如下:

/* UVA10074 Take the Land */

#include <bits/stdc++.h>

using namespace std;

const int N = 100;
int sum[N + 1][N + 1], dp[N + 1];
const int M1000 = - (N + 1) * (N + 1);

int main()
{
    int m, n, a;
    while(~scanf("%d%d", &m, &n) && (m || n)) {
        memset(sum, 0, sizeof(sum));

        for(int i = 1; i <= m; i++) {
            sum[i][0] = 0;
            for(int j = 1; j <= n; j++) {
                scanf("%d", &a);
                a = a ? M1000 : 1;
                sum[i][j] = sum[i][j - 1] + a;
            }
        }

        // 按第i-j列,对所有的行计算最大子段和
        int ans = 0;
        for(int i = 1; i <= n; i++)
            for(int j = i; j <= n; j++) {
                memset(dp, 0, sizeof(dp));
                for(int k = 1; k <= m; k++) {
                    if(dp[k - 1] > 0)
                        dp[k] = dp[k - 1] + (sum[k][j] - sum[k][i - 1]);
                    else
                        dp[k] = sum[k][j] - sum[k][i - 1];
                    ans = max(ans, dp[k]);
                }
            }

        printf("%d\n", ans);
    }

    return 0;
}

/*
4 9
1 0 0 0 1 1 1 0 1
1 1 1 1 0 1 0 1 0
1 0 0 1 0 0 0 1 0
0 1 0 0 1 0 0 1 1

4
*/

AC的C++语言程序如下:

/* UVA10074 Take the Land */

#include <bits/stdc++.h>

using namespace std;

const int N = 100;
int sum[N + 1][N + 1];
const int M1000 = - (N + 1) * (N + 1);

int main()
{
    int m, n, a;
    while(~scanf("%d%d", &m, &n) && (m || n)) {
        memset(sum, 0, sizeof(sum));

        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++) {
                scanf("%d", &a);
                a = a ? M1000 : 1;
                sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a;
            }

        int ans = 0;
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
                for (int p = i; p <= m; p++)
                    for (int q = j; q <= n; q++) {
                        int t = sum[p][q] - sum[p][j - 1] - sum[i - 1][q] + sum[i - 1][j - 1];
                        ans = max(ans, t);
                    }

        printf("%d\n", ans);
    }

    return 0;
}
发布了2289 篇原创文章 · 获赞 2373 · 访问量 265万+

猜你喜欢

转载自blog.csdn.net/tigerisland45/article/details/105342537