【循环数组的最大字串和】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;
    }
}

原文地址:https://www.cnblogs.com/NeilThang/p/10269364.html

时间: 2024-10-03 03:14:02

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

最大字串和

最大字串和: #include <iostream> using namespace std; //求最大字串和:返回最大和 int maxSubSum(int a[], int len) { int sum = 0; //全局最大值 int temp = 0; //局部最大值 for(int i = 0; i < len; ++i) { if(temp > 0) //如果局部最大值大于0,则继续求和,否则以数组当前元素重新初始化 { temp += a[i]; } else te

lintcode循环数组之连续子数组求和

v 题目:连续子数组求和 II 给定一个整数循环数组(头尾相接),请找出一个连续的子数组,使得该子数组的和最大.输出答案时,请分别返回第一个数字和最后一个数字的值.如果多个答案,请返回其中任意一个. v 样例 给定 [3, 1, -100, -3, 4], 返回 [4,0]. v 思路 1.如果不是循环数组,求解连续子区间和的思路如下: 首先设一个累加变量和sum和最大值变量maxN,[ld, rd]表示当前正在累加的区间,[lt,rt]表示最大和的区间.从左边开始一直累加,并初始当前区间[ld

二维循环数组

一.题目与要求 题目.返回一个二维整数数组中最大子数组的和 要求.1.输入一个二维整形数组,数组里有正数也有负数. 2.二维数组首尾相接,象个一条首尾相接带子一样. 3.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和 二.设计思路 在上一次的以为循环数组的基础上,和二维数组求最大子数组相结合,将功能合并,完成题目要求. 第一步.将每一行的数组作为循环数组求最大子数组 第二步.通过枚举的方式,将每一种情况的和存入到新建二维数组中 第三部.通过逐列计算最大子数组的方法求所有子矩阵的最

基于循环数组的无锁队列

在之前的两篇博客(线程安全的无锁RingBuffer的实现,多个写线程一个读线程的无锁队列实现)中,分别写了在只有一个读线程.一个写线程的情况下,以及只有一个写线程.两个读线程的情况下,不采用加锁技术,甚至原子运算的循环队列的实现.但是,在其他的情况下,我们也需要尽可能高效的线程安全的队列的实现.本文实现了一种基于循环数组和原子运算的无锁队列.采用原子运算(compare and swap)而不是加锁同步,可以很大的提高运行效率.之所以用循环数组,是因为这样在使用过程中不需要反复开辟内存空间,可

Smarty教程1.引擎定义2.主要优点3.简明教程4.使用判断5.循环数组6.常见问题8.解释程序

Smarty是一个php模板引擎.更准确的说,它分开了逻辑程序和外在的内容,提供了一种易于管理的方法.可以描述为应用程序员和美工扮演了不同的角色,因为在大多数情况下 ,他们不可能是同一个人.例如,你正在创建一个用于浏览新闻的网页,新闻标题,标签栏,作者和内容等都是内容要素,他们并不包含应该怎样去呈现.在Smarty的程序里,这些被忽略了.模板设计者们编辑模板,组合使用html标签和模板标签去格式化这些要素的输出(html表格,背景色,字体大小,样式表,等等).有一天程序员想要改变文章检索的方式(

数组及字符、串、正则API总结

数组及字符.串.正则API 序号 名称及功能 函数 操作对象类型 返回值 语法 修改原 备注 案例 数组 字串 1 数组转字串 String() 数组 字串 str var str=String(arr) 否 默认逗号分隔   2 拼接数组元素为字串 join() 数组 字串 str   否 略后,用逗 无缝拼接 3 拼接数组为字串 concat() 数组 字串 newArr var newArr=arr.concat(值1,值2,[],...) 否     4 截取子 slice() 数组 字

返回一个二维循环数组中最大子矩阵的和

设计思路 和一维循环数组思路相仿,循环N次,每次将第一列的数移到最后一列,新建一个相同规格的二维数组来存放新矩阵,将之前写的求二维数组最大子矩阵的和的算法稍作修改,添加一个循环即可满足要求. 源程序代码 #include<iostream> #include <cstdlib> #include <ctime> using namespace std; #define M 4 #define N 4 void main() { int a[M][N],aa[M][N],

循环数组求最大子数组

一.题目要求 题目:返回一个整数数组中最大子数组的和. 要求: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大. 同时返回最大子数组的位置. 求所有子数组的和的最大值.要求时间复杂度为O(n). 二.设计思想 把数组每一位向后移动一位,最后一位放在第一位.循环多次,每次求其最大子数组,存放到新数组内,比较新数组中最大数,

首尾相连的循环数组求其子数组最大值

结对成员 曹坤  翟凯 题目 返回一个整数数组中最大子数组的和. 要求: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大. 同时返回最大子数组的位置. 思路 经过讨论,只需将数组扩展为2倍长度,array[i]=array[length+i];从第一个元素开始依 次五个元素为一组,共分为五组进行:分别求得五个最大子数组和