洛谷P2331 [SCOI2005] 最大子矩阵[序列DP]

题目描述

这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。

输入输出格式

输入格式:

第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。

输出格式:

只有一行为k个子矩阵分值之和最大为多少。

输入输出样例

输入样例#1:

3 2 2
1 -3
2 3
-2 3

输出样例#1:

9

m分类讨论m=1,f[i][j]表示前i个选了j个矩阵m=2,f[i][j][k]表示第一行前i个第二行前j个选了k个矩阵,转移注意i==j可以上下都选数据弱,随便一个全负的矩阵就把没初始化的卡住了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=105,INF=1e9+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}
int n,m,K,a[N][3],d[N][15],s[N][3],ans=-INF;
void dp1(){
    for(int i=1;i<=n;i++)
        s[i][1]=s[i-1][1]+a[i][1];
    for(int j=1;j<=K;j++) d[0][j]=-INF;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=K;j++){
            d[i][j]=d[i-1][j];
            for(int z=0;z<i;z++) d[i][j]=max(d[i][j],d[z][j-1]+s[i][1]-s[z][1]);
        }
}
int f[N][N][15];
void dp2(){
    for(int i=1;i<=n;i++){
        s[i][1]=s[i-1][1]+a[i][1]; //printf("s1 %d %d \n",i,s[i][1]);
        s[i][2]=s[i-1][2]+a[i][2];    //printf("s2 %d %d \n",i,s[i][2]);
    }
    for(int i=1;i<=max(n,m);i++) for(int j=1;j<=K;j++) f[i][0][j]=f[0][i][j]=-INF;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int k=1;k<=K;k++){
                f[i][j][k]=max(f[i-1][j][k],f[i][j-1][k]);
                for(int z=0;z<i;z++) f[i][j][k]=max(f[i][j][k],f[z][j][k-1]+s[i][1]-s[z][1]);
                for(int z=0;z<j;z++) f[i][j][k]=max(f[i][j][k],f[i][z][k-1]+s[j][2]-s[z][2]);
                if(i==j) for(int z=0;z<i;z++)
                    f[i][j][k]=max(f[i][j][k],f[z][z][k-1]+s[i][1]-s[z][1]+s[i][2]-s[z][2]);
                //printf("f %d %d %d %d\n",i,j,k,f[i][j][k]);
            }
}
int main(int argc, const char * argv[]) {
    n=read();m=read();K=read();
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read();
    if(m==1) {dp1();printf("%d",d[n][K]);}
    else {dp2();printf("%d",f[n][n][K]);}
    //printf("\n\n%d",a[1][2]);
    return 0;
}
 
时间: 2024-10-18 08:52:49

洛谷P2331 [SCOI2005] 最大子矩阵[序列DP]的相关文章

洛谷P2327 [SCOI2005]扫雷 枚举 搜索

洛谷P2327 [SCOI2005]扫雷 枚举 搜索 对搜索的 一些优化 其实我们只要枚举第一行是否有地雷,根据第1行探测出的地雷数,就可以推出第二行是否有地雷 然后在根据第二行探测地雷数推出第三行的情况,这样以此类推,一直推到第 n-1 的探测结果,然后 推出第 n 行是否有地雷如果在推的过程中 使得当前的探测地雷数为 负数 ,说明这个方法是萎的, 或者这一行推完了之后,还是有雷,那也退出,最后还要判断一下第 n 行是否有地雷 1 #include <cstdio> 2 #include &

洛谷P1122 最大子树和 树形DP

洛谷P1122 最大子树和一道类似树形DP 的题目 首先我们随意定根 ,假设我们定根为 1, 那么我们设dp[ i ] 表示 在这个整个以1为根的树中 以 i为根的子树 i 这个点强制取到 , 我们再从他的子树中取出一部分出来,最大能够取到的和 我们可知 当 枚举到dp[ u ] 时 ,我们看他的儿子取不取 如果v是它的儿子 若dp[ v ] > 0 那么我们就取 ,否则就不取,取了反而会减少 这样类似最长连续子序列一样就行了 然后类似树形DP 一样从根节点向根扩展就行了 ,也就是dfs下去 然

洛谷P1063 能量项链(区间DP)(环形DP)

To 洛谷.1063 能量项链 题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记.因为只有这样,通过吸盘(吸盘是Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量.如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为m*r*n(M

洛谷 P1280 尼克的任务 ( 线性DP )

题意 :  尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成.尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束.当尼克到达单位后他就开始干活.如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成.如果某任务于第P分钟开始,持续时间为T分钟,则该任务将

缩点(洛谷3387)——不会写DP 的我只好来了个SPFA

我刚开始也不知道为什么就想到肯定是缩了点后把一个新点(原图中的强连通分量)的权值赋为它所含的所有点的权值之和,没有想着去推,纯粹是题目的名字启发我这么去干的……之后用SPFA 求最大路径,然而我连的全是无向边,导致答案错误了四个点,发现错误后觉得,之前的代码居然还对了六个点才是最让人震惊的. 1 #include<queue> 2 #include<stack> 3 #include<vector> 4 #include<iostream> 5 #inclu

洛谷P3047 [USACO12FEB]Nearby Cows(树形dp)

P3047 [USACO12FEB]附近的牛Nearby Cows 题目描述 Farmer John has noticed that his cows often move between nearby fields. Taking this into account, he wants to plant enough grass in each of his fields not only for the cows situated initially in that field, but

P2331 [SCOI2005]最大子矩阵

题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式: 第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767). 输出格式: 只有一行为k个子矩阵分值之和最大为多少. 输入输出样例 输入样例#1: 3 2 2 1 -3 2 3 -2 3 输出样例#1: 9 读完题目之后我们可以发现:这个数据的m==2.那么就

洛谷 P2324 [SCOI2005]骑士精神

P2324 [SCOI2005]骑士精神 题目描述 输入输出格式 输入格式: 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位.两组数据之间没有空行. 输出格式: 对于每组数据都输出一行.如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1. 输入输出样例 输入样例#1: 2 10110 01*11 10111 01001 00000 01011 110*1 01110 01010 00100 输出样例

洛谷 P2327 [SCOI2005]扫雷

P2327 [SCOI2005]扫雷 https://www.luogu.org/problem/show?pid=2327 题目描述 输入输出格式 输入格式: 第一行为N,第二行有N个数,依次为第二列的格子中的数.(1<= N <= 10000) 输出格式: 一个数,即第一列中雷的摆放方案数. 输入输出样例 输入样例#1: 2 1 1 输出样例#1: 2 算法1: 枚举左边每个位置是否有雷,复杂度O(2^n*n). 算法2: 我们发现,当前两个位置确定时,后面的位置也就可以推出来了. 于是我