• 【循环数组的最大字串和】Maximal-sum Subsequence


    【循环数组的最大字串和】Maximal-sum Subsequence

    PROBLEM

    题目描述

    给一个 N×N 的矩阵 M,可以取连续的一段数(必须是横着或者竖着或者斜着,这个矩阵是循环的,具体如下)。要求找到一个子序列,使得这个序列的和最大。

    对于 N=8 的矩阵,如下序列都是合法的:
    ​ M2,1,M2,2,M2,3,M2,4,M2,5,M2,6,M2,7,M2,8.
    ​ M2,2,M2,3,M2,4.
    ​ M2,6,M2,7,M2,8,M2,1,M2,2.
    ​ M4,3,M5,3,M6,3,M7,3.
    ​ M1,2,M2,3,M3,4,M4,5.
    ​ M2,4,M3,3,M4,2,M5,1.
    ​ M3,3,M4,2,M5,1,M1,5. (按样例理解是M8,6 ,emmmmm)
    ​ M5,6.
    一个元素不可取多次,取的必须是连续的一段。
    可以什么都不取(即答案为 0)。

    输入

    第一行一个数 T (T≤30),表示数据组数。
    每一组数据第一行为一个正整数 N (1≤N≤1000)。
    接下来 N 行每行 N 个数表示这个矩阵。(每个元素大小在 −32768 到 32767 之间)

    输出

    每组数据一行表示最大的序列和。

    样例输入

    1
    4 
    8 6 6 1
    -3 4 0 5
    4 2 1 9
    1 -9 9 -2
    

    样例输出

    24
    

    提示

    样例解释:选取序列 M3,4,M4,3,M1,2。

    SOLUTION

    题面好像有点问题,应该按照提示(样例)来理解。
    首先你要会如何求数组的最大字串和。
    然后循环数组最大字串和 = max(数组求和+数组元素取反后的最大字串和,原数组的最大字串和)
    最后每行每列以及所有斜向上的答案取最值即可。

    CODE

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int MAXN = 2005;
    
    int martix[MAXN][MAXN];
    
    int dp[MAXN];
    
    int py(int x,int n){
        while (x<0)x+=n;
        while (x>=n)x-=n;
        return x;
    }
    
    int cal(int arr[],int n) {
        int sum = 0;
        memset(dp, 0, sizeof(dp));
        sum = dp[0] = arr[0];
        for (int i = 1; i < n; i++) {
            dp[i] = max(arr[i], dp[i-1]+arr[i]);
            sum += arr[i];
        }
        int ans = 0;
        for (int i = 1; i < n; i++) {
            if (dp[i] > dp[ans]) {
                ans = i;
            }
        }
        int ans1 =  dp[ans];
        for (int i = 0; i < n; i++) {
            arr[i] = -arr[i];
        }
        memset(dp, 0, sizeof(dp));
        dp[0] = arr[0];
        for (int i = 1; i < n; i++) {
            dp[i] = max(arr[i], dp[i-1]+arr[i]);
        }
        ans = 0;
        for (int i = 1; i < n; i++) {
            if (dp[i] > dp[ans]) {
                ans = i;
            }
        }
        int ans2 = dp[ans];
        return max(ans1,ans2+sum);
    }
    
    int main(){
        int T;
        for(scanf("%d",&T);T;T--){
            int n;
            scanf("%d",&n);
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    scanf("%d",&martix[i][j]);
                }
            }
            int ans = 0;
            for(int i=0;i<n;i++){
                int carry[MAXN];
                for(int j=0;j<n;j++){
                    carry[j] = martix[i][j];
                }
                ans = max(ans,cal(carry,n));
                for(int j=0;j<n;j++){
                    carry[j] = martix[j][i];
                }
                ans = max(ans,cal(carry,n));
                for(int j=0;j<n;j++){
                    carry[j] = martix[py(i-j,n)][py(j,n)];
                }
                ans = max(ans,cal(carry,n));
                for(int j=0;j<n;j++){
                    carry[j] = martix[py(i-j,n)][py(n-j-1,n)];
                }
                ans = max(ans,cal(carry,n));
            }
            cout<<ans<<endl;
        }
    }
    
  • 相关阅读:
    20155302 《信息安全系统设计基础》课程总结
    2017-2018-1 20155302 第十四周作业
    2017-2018-1 20155302 第十三周作业
    2017-2018-1 20155302 实验五 通信协议设计
    20155302实验一
    2017-2018-1 20155302 实验四 外设驱动程序设计
    2017-2018-1 20155302 《信息安全系统设计基础》第11周学习总结
    # 2017-2018-1 20155302 课下实践IPC及课上补充
    2017-2018-1 20155302 实验三 实时系统
    # 2017-2018-1 20155302 《信息安全系统设计基础》第9周学习总结
  • 原文地址:https://www.cnblogs.com/NeilThang/p/10269364.html
Copyright © 2020-2023  润新知