zoukankan      html  css  js  c++  java
  • [POJ 1050]To the Max

     给出一个数字矩阵,求子矩阵数字之和的最大值.这是最大子段和问题.(该题的AC代码

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int n, a;
    long long sum, ans = -100000000;
    
    int main(){
        cin >> n;
        for(int i = 0; i < n; i++){
            cin >> a;
            sum += a;
            ans = max(ans, sum);
            if(sum < 0) sum = 0;
        }
        cout << ans << endl;
    
        return 0;
    }
    View Code

    ,注意输入全为负数的情况)

    上述一维情况本质上是在枚举和剪枝,可以通过简单的单层循环实现,发现和为负数时舍弃当前子段.

    而二维情况下,没有办法这样"线性"枚举,想要舍弃时也有所顾虑.

    由于数据比较小(n <= 100),直接暴力枚举子矩阵的左上角坐标(x1,y1)和右下角坐标(y1,y2)求解.O(n4)(粗略的)也不会爆.因为右下角坐标总是在左上角坐标之右下.

    如何计算子矩阵数字之和?不用前缀和的话复杂度会变成O(n6).

    从坐标(x1+1,y1+1)到(x2,y2)的所有数字之和即为:

    s[x2][y2] + s[x1][y1] - s[x2][y1] - s[x1][y2]

    由于矩阵是按从左上到右下的顺序给出的,前缀和在读入时就可以计算了.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int n, s[110][110], ans = -100000000;    // 同样要考虑全为负数情况
    
    int main(){
        cin >> n;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++){
                cin >> s[i][j];
                s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
            }
    
        for(int x1 = 0; x1 <= n - 1; x1++)
            for(int y1 = 0; y1 <= n - 1; y1++)
                for(int x2 = x1 + 1; x2 <= n; x2++)
                    for(int y2 = y1 + 1; y2 <= n; y2++)
                        ans = max(ans, s[x2][y2] + s[x1][y1] - s[x2][y1] - s[x1][y2]);
        cout << ans << endl;
    
        return 0;
    }
  • 相关阅读:
    原生js 异步请求,responseXML解析
    asp.net中Page.ClientScript.RegisterStartupScript用法小结
    asp.net 在repeater控件中加按钮
    无法打开物理文件 操作系统错误 5:拒绝访问 SQL Sever
    js 注册控件的onclick事件
    js控件设置只读属性和不可用属性
    js CheckBox只读
    js时间日期格式
    js正则判断日期
    UIPickerView的使用(三)
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14148080.html
Copyright © 2011-2022 走看看