Codevs 2482 宝库通道 2007年省队选拔赛安徽

2482 宝库通道 2007年省队选拔赛安徽
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 大师 Master
题目描述 Description
探宝的旅程仍然继续中,由于你的帮助,小可可成功点燃了灯阵,避过了许多致命的陷阱,终于来到了宫殿的正厅中。大厅的地面是由一块块大小一致的正方形石块组成的,这些石块分为黑、白两色,组成了一个m*n的矩形,在其中一个石块的下面就是通往藏宝库的通道。小可可不可能一个一个石块的尝试,因为有些石块安装了机关,一碰就会触发,整个宫殿也随之倒塌。根据藏宝图记载,通道在某一特定的区域中,这个区域是一个由数个石块组成的面积不为0的小矩形,它的四条边与大厅地面的边平行。如果对整个大厅地面任意划分矩形,那么在所有矩形中,这个区域的黑色石块数目减去白色石块数目所得的差是最大的。
小可可希望和你分工,由他来选择区域,你来计算黑、白两色石块的数目差S。这样就能快速而准确的确认通道所在的区域。藏宝图上说这个区域中的石块都没有安装机关,只要确定了区域,就一定能找到通道。宝藏就在眼前了,加油吧!(假设用1表示黑色石块,用0表示白色石块)
输入描述 Input Description
输入文件的第一行为两个整数m,n (1<=m,n<=400).
以下m行,每行n个字符,每个字符都是0或1。
输出描述 Output Description
输出文件仅一个数,表示所有可能的区域中S值(见前文描述)最大的一个,输出这个值即可。
样例输入 Sample Input
3 4
1011
1111
1111
样例输出 Sample Output
10
数据范围及提示 Data Size & Hint
见题面
分类标签 Tags
安徽 省队选拔赛 2007年

/*
DP.
这题就是求最大子矩阵和.
因为要求矩阵中‘1’的个数-‘0’的个数.
所以直接把‘0’改成‘-1’就好了.
然后n^3跑最大子矩阵和.
i,j分别枚举目前矩阵的始末行.
然后把每列的元素加起来.
转化成一维的最大子段和.
*/
#include<iostream>
#include<cstdio>
#define MAXN 401
using namespace std;
int n,m,s[MAXN][MAXN],ans=-1e9,b[MAXN];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
    return x*f;
}
int main()
{
    n=read();m=read();char ch;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
      {
        cin>>ch;
        if(ch=='1') s[i][j]=1;
        else s[i][j]=-1;
      }
    for(int i=1;i<=n;i++)
    {
        for(int k=1;k<=m;k++)  b[k]=0;
        for(int j=i;j<=n;j++)
        {
            for(int k=1;k<=m;k++)
              b[k]+=s[j][k];
            int tot=b[1];ans=max(tot,ans);
            for(int j=2;j<=m;j++)
              if(tot>=0) tot+=b[j],ans=max(tot,ans);
              else tot=b[j],ans=max(tot,ans);
        }
    }
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/nancheng58/p/10068209.html