[NOIP2014]子矩阵

1812. [NOIP2014]子矩阵

http://www.cogs.pro/cogs/problem/problem.php?pid=1812

★★★   输入文件:submatrix.in   输出文件:submatrix.out   简单对比
时间限制:1 s   内存限制:256 MB

【题目描述】

最暴力的算法是枚举选择哪些行、列。复杂度为O(C(n,r)*C(m,c))。不过显然不能承受。(C为组合数)

注意到虽然O(C(n,r)*C(m,c))不能承受,但O(C(n,r))或O(C(m,c))是可以接受的。

不妨考虑枚举其中一个(假设枚举行)。

枚举完行后,由于行已确定,因此可以把所有行捆绑,视为一个整体。

处理处列与列之间的价值,然后可以用动态规划解决这个问题。

设dp[i][k]表示前i列选了k列,并且第i列强制被选。那么转移方程为:dp[i][k]=dp[j][k-1]+cost[j][i]+val[i],其中j<i,cost[j][i]表示第i列与第j列相邻的花费,val[i]表示第i列内的花费。

答案即为min{dp[i][c]}。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
using namespace std;
int a[20][20],m,n,r,c,lr[20],ud[20],dp[20][20];
int rlc[20],udc[20][20],ans=0x7fffffff;
void Dp(){
    memset(rlc,0,sizeof(rlc));
    memset(udc,0,sizeof(udc));
    memset(dp,127/3,sizeof(dp));
    //不同列之间的差
    for(int i=1;i<=m;i++)
        for(int j=1;j<i;j++)
            for(int k=1;k<=r;k++)
                udc[j][i]+=abs(a[lr[k]][i]-a[lr[k]][j]);
    //不同行之间的差
    for(int i=1;i<=m;i++)
        for(int j=1;j<r;j++)
            rlc[i]+=abs(a[lr[j]][i]-a[lr[j+1]][i]);
    for(int i=1;i<=n;i++)dp[i][0]=0,dp[i][1]=rlc[i];
    for(int i=1;i<=c;i++){
        for(int j=i;j<=m;j++){
            for(int k=i-1;k<j;k++){
                dp[j][i]=min(dp[k][i-1]+udc[k][j]+rlc[j],dp[j][i]);
            }
        }
    }
    for(int i=c;i<=m;i++)ans=min(ans,dp[i][c]);
}
void dfs(int Step,int rest){
    if(Step==r){Dp();return;}
    if(r-Step>rest)return;
    for(int i=rest;i>=1;i--){lr[Step+1]=i;dfs(Step+1,i-1);}
}
int main(){
    freopen("submatrix.in","r",stdin);
    freopen("submatrix.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&r,&c);
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&a[i][j]);
    dfs(0,n);
    printf("%d",ans);
}
时间: 2024-10-28 20:44:22

[NOIP2014]子矩阵的相关文章

[NOIP2014]子矩阵解题报告

这题看上去没啥思路,一看数据范围小的可怜,就算了下暴搜的时间复杂度O(C(16,8)?(C(16,8)+m3))≈108似乎没啥问题,然后就写了个暴搜,出了点数据发现T了,又加了个剪枝然后就A了.. 结果一看人家的代码全是DP..让我有点蛋疼. 其实只要把暴搜的后半部分一改就可以了,把二维压成一维后,就有一个显然的DP方程:处理出选一列的代价lsi,选一对列的代价hs(i,j),设f(i,j)为选第i列,在第i列之前已经选了j-1列的最小代价,则显然 f(i,j)=lsi+min1≤k<i{ f

1768:最大子矩阵(NOIP2014初赛最后一题)

1768:最大子矩阵 总时间限制: 1000ms 内存限制: 65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的矩阵 0 -2 -7 0 9 2 -6 2-4 1 -4 1-1 8 0 -2 的最大子矩阵是 9 2-4 1-1 8 这个子矩阵的大小是15. 输入 输入是一个N * N的矩阵.输入的第一行给出N (0 < N <= 100).再后面的若干行中,依次(首先从左到右给出第一行的N

【NOIP2014】子矩阵

这题如果按暴力做只有一半分,最大时间复杂度为O(C(8,16)*C(8,16)); 很容易算出超时: 我们可以发现如果直接dp会很难想,但是知道选哪几行去dp就很好写状态转移方程: dp[i][j]=min(dp[i][j],dp[k][j-1]+a[i]+b[k][i]); 其中dp[i][j]表示 前i列里选j列的子矩阵最大分值 a[i]表示 第i列选到的行的总差值 b[k][i]表示选到的每一行第k列和第i列之间的差值 我们只要枚举 行 然后dp一次,取最小值即可 这样最大时间复杂度就成了

BZOJ 1084 最大子矩阵 终于过了

一开始看到这道题,由于觉得m <= 2, 所以觉得这是道水题,回去后想了一下.在晚上来机房的时候已经想出来了,但是我必须承认细节决定成败.远在一个小时前我就已经把算法的主体都写好了,但是就是一直WA,为什么就是各种粗心,真心想捏死自己.一个小时就这么白白浪费了.我希望明天的我能变得强大一点.在有了今日惨痛的教训之后. 这道题并不难.用d[i][j][k] 来表示状态.i表示第几行,j表示之前取了多少个矩阵,k表示上一行的状态.即上一行的矩阵取法.如果k == 0 那么没有一个矩阵延伸到上一行,如

poj1050查找最大子矩阵和

题目: To the Max Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 48507   Accepted: 25662 Description Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1*1 or greater locate

Codevs 1159 最大全0子矩阵 悬线法!!!!

1159 最大全0子矩阵 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O的个数最多. 输入描述 Input Description 输入文件第一行为整数N,其中1<=N<=2000,为方阵的大小,紧接着N行每行均有N个0或1,相邻两数间严格用一个空格隔开. 输出描述 Output Description 输出文件仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数.

51nod 1051 求最大子矩阵和

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1051 1051 最大子矩阵和 基准时间限制:2 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 一个M*N的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值. 例如:3*3的矩阵: -1 3 -1 2 -1 3 -3 1 2 和最大的子矩阵是: 3 -1 -1 3 1 2 Input 第1行:M和N,中间用空格

2014子矩阵

题目描述 Description 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与 列的相对顺序)被称为原矩阵的一个子矩阵.例如,下面左图中选取第 2.4 行和第 2.4.5 列交叉位置的元素得到一个 2*3 的子矩阵如右图所示. 相邻的元素:矩阵中的某个元素与其上下左右四个元素(如果存在的话)是相邻的. 矩阵的分值:矩阵中每一对相邻元素之差的绝对值之和. 本题任务:给定一个 n 行 m 列的正整数矩阵,请你从这个矩阵中选出一个 r 行 c 列的 子矩阵,

BZOJ1084 [SCOI2005]最大子矩阵

Description 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. Input 第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767). Output 只有一行为k个子矩阵分值之和最大为多少. Sample Input 3 2 2 1 -3 2 3 -2 3 Sample Output 9 正解:DP 解题报告: 乍一看,感觉像是才