hdu1559,1081最大子矩阵和的两种题型

最大子矩阵是一种典型的dp问题。某种程度上说是最大连续子序列和问题的扩展。

1081

原题地址

这是最常见的最大子矩阵问题的体型。简单的解决方案就是把列累加,遍历任意两行的累加值的差值,然后就转换成了普通的最大连续子序列和问题。从而将二维问题转换为一维。时间复杂度较高为O(N^3)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX=104;
int a[MAX][MAX];
int dp[MAX];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(a,0,sizeof a);
        memset(dp,0,sizeof dp);
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%d",&a[i][j]);
                a[i][j]+=a[i-1][j];
            }
        }
        int max_sum=0;
        for(int i=1; i<=n; i++)
        {
            for(int j=0; j<i; j++)
            {
                for(int k=1; k<=n; k++)
                {
                    dp[k]=a[i][k]-a[j][k];
                    dp[k]+=dp[k-1];
                    if(dp[k]<0)
                        dp[k]=0;
                    if(dp[k]>max_sum)
                        max_sum=dp[k];
                }
            }
        }
        printf("%d\n",max_sum);
    }
}

在输入矩阵值的时候做了处理,a[i][j]+=a[i-1][j] 使得a矩阵中a[i][k]保存的是原矩阵中第k列元素,从上累加到第i个元素的和。

所以下面的dp[k]=a[i][k]-a[j][k],dp[k]表示的就是原矩阵第k列中,第i行到第j行的元素和。

三层for循环,前两层循环为遍历任意两行的差值。也就是说遍历子矩阵的首行和尾行的所有情况。

内部第三层for循环,就是一般的求解一维最大连续子序列和的求法。

1559

原题地址

这道题与上题不同,它加了两个限制条件,就是子矩阵的两个维度必须是给定的x,y值。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX=1004;
int a[MAX][MAX];
int dp[MAX];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int m,n,x,y;
        memset(a,0,sizeof a);
        scanf("%d%d%d%d",&m,&n,&x,&y);
        for(int i=1; i<=m; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%d",&a[i][j]);
                a[i][j]+=a[i-1][j];
            }
        }
        int max_sum=0;
        for(int i=x; i<=m; i++)
        {
            for(int j=1; j<=n; j++)
            {
                dp[j]=a[i][j]-a[i-x][j];
                dp[j]+=dp[j-1];
                if(j>=y)
                {
                    max_sum=max(max_sum,dp[j]-dp[j-y]);
                }
            }
        }
        printf("%d\n",max_sum);
    }
}

大同小异,关键在于 决策 之时。dp[j]-dp[j-y]表示原矩阵中以(i,j)为右下角元素,行数为x,列数为y的子矩阵和。

hdu1559,1081最大子矩阵和的两种题型

时间: 2024-10-06 15:38:50

hdu1559,1081最大子矩阵和的两种题型的相关文章

一、查看Linux内核版本命令(两种方法):

一.查看Linux内核版本命令(两种方法): 1.cat /proc/version [[email protected]CentOS home]# cat /proc/versionLinux version 2.6.32-431.el6.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Nov 22 03:15:09 UTC 2013 2.uname -a [

两种插入排序算法java实现

两种方法都编译运行通过,可以当做排序类直接使用. 折半插入排序: public class Sort1 { public static void main(String[] args) { InsertSort sort = new InsertSort(); sort.InsertSort(); int[] arr = sort.getarr(); System.out.println(); System.out.println("排序之后:"); for (int ar : arr

hibernate载入持久化对象的两种方式——get、load

一.get与load对照 在hibernate中get和load方法是依据id取得持久化对象的两种方法.但在实际使用的过程中总会把两者混淆,不知道什么情况下使用get好,什么时候使用load方法效率更高.下边具体说一下get和load的不同,有些时候为了对照也会把find加进来. 1.从返回结果上对照: load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常 get方法检索不到的话会返回null 2.从检索运行机制上对照: get方法和fin

Jmeter 跨线程组传递参数 之两种方法

终于搞定了Jmeter跨线程组之间传递参数,这样就不用每次发送请求B之前,都需要同时发送一下登录接口(因为同一个线程组下的请求是同时发送的),只需要发送一次登录请求,请求B直接用登录请求的参数即可,直到登录接口的参数失效了,需再次发送一次登录接口,又可以多次使用其参数,下面举例子: 1.登录接口中利用 Json Path Extractor 获取到登录接口的响应参数,(怎么获取上一节讲过) 终于搞定了Jmeter跨线程组之间传递参数,这样就不用每次发送请求B之前,都需要同时发送一下登录接口(因为

第十九篇:处理僵尸进程的两种经典方法

前言 如果父进程没有结束,而子进程终止了.那么在父进程调用 wait 函数回收这个子进程或者父进程终止以前,这个子进程将一直是僵尸进程. 本文将提供两种方法处理这个问题. 方法一:父进程回收法 wait函数将使其调用者阻塞,直到其某个子进程终止.故父进程可调用wait函数回收其僵尸子进程.除此之外,waitpid函数提供更为详尽的功能( 增加了非阻塞功能以及指定等待功能 ),请读者自行查阅相关资料. 代码实现 1 #include <unistd.h> 2 #include <sys/w

maven的两种可运行jar打包方式。1、内置依赖,2、外部依赖。

maven打可运行jar包的两种方式 maven常用的普通打包方式分为pom,jar,war等,至于这些打包类型就不介绍啦. 如果不进行特殊配置,那么打包出来的jar包是不可运行的.只能当作普通依赖包使用. 下面就介绍两种maven打可运行jar包的方式: 方式一:内置打包法 <plugins> <!-- 内置打包法 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <!-- 

em创建的两种方式

em创建(两种方式1,图形dbca,当然了,前提是先创建一个监听. 2,手工命令安装em)手工命令创建em(确保数据库开启,确保监听正常并且最好是动态监听,确保system表空间够用大概1G左右),我的空间有限只给了800M,如下 select file_name,tablespace_name,bytes/1024/1024 from dba_data_files where tablespace_name like 'SYSTEM';alter database datafile '/u01

利用颜色和形态学两种方法进行车牌区域提取的OpenCV代码

要想提取车牌号,首先你要定位车牌区域嘛,本文分别两种方法用,即颜色和形态学的方法,对车牌区域进行判定.说得是两种方法,其实两种方法并无多大的区别,只是有一步的判断标准不一样而已,你看了下面整理出的的思路就知道两者的区别真的很小了. 方法一:利用颜色提取车牌区域的思路: ①求得原图像的sobel边缘sobelMat ②在HSV空间内利用车牌颜色阈值对图像进行二值化处理,得到图像bw_blue→ ③由下面的判别标准得到图像bw_blue_edge for (int k = 1; k != heigh

ios图片拉伸两种方法

ios图片拉伸两种方法 UIImage *image = [UIImage imageNamed:@"qq"]; 第一种: // 左端盖宽度 NSInteger leftCapWidth = image.size.width * 0.5f; // 顶端盖高度 NSInteger topCapHeight = image.size.height * 0.5f; // 重新赋值 image = [image stretchableImageWithLeftCapWidth:leftCapW