zoukankan      html  css  js  c++  java
  • 【BZOJ1084】最大子矩阵(动态规划)

    【BZOJ1084】最大子矩阵(动态规划)

    题面

    题目描述

    这里有一个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)
    。。。
    是我太菜,什么都看不见
    既然(m≤2),那么分情况直接搞就行了

    第一种 (m=1)

    很显然吧。。
    (f[i][j])表示当前搞到第(i)行,已经选了(j)个子矩阵的最大值
    暴力枚举一下上一个开始的位置
    然后前缀和转移即可

    第二种 (m=2)

    (f[i][j][k])表示当前第一列的搞到(i),第二列的搞到(j),一共选了(k)个子矩阵的最大值
    首先上下两列分开搞,类似(m=1)的转移,
    然后当(i=j)时,显然可以两列一起转移
    所以也类似于(m=1)的转移,
    求和的时候搞两列的就行了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    int n,m,g[200][5];
    int K,f[101][101][15],s[5][200];
    int ff[101][15];
    int main()
    {
    	n=read();m=read();K=read();
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			g[i][j]=read();
    	for(int j=1;j<=m;++j)
    		for(int i=1;i<=n;++i)
    			s[j][i]=s[j][i-1]+g[i][j];
    	if(m==1)
    	{
    		memset(ff,-63,sizeof(ff));
    		ff[0][0]=0;
    		for(int i=1;i<=n;++i)
    		{
    			ff[i][0]=0;
    			for(int k=1;k<=K;++k)
    			{
    				ff[i][k]=ff[i-1][k];//不选
    				for(int j=0;j<i;++j)
    					ff[i][k]=max(ff[i][k],ff[j][k-1]+s[1][i]-s[1][j]);
    			}
    		}
    		printf("%d
    ",ff[n][K]);
    	}
    	else
    	{
    		memset(f,-63,sizeof(f));
    		for(int i=0;i<=n;++i)
    			for(int j=0;j<=n;++j)
    				f[i][j][0]=0;
    		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][j][k],f[i-1][j][k]);
    					f[i][j][k]=max(f[i][j][k],f[i][j-1][k]);
    					for(int l=0;l<i;++l)
    						f[i][j][k]=max(f[i][j][k],f[l][j][k-1]+s[1][i]-s[1][l]);
    					for(int l=0;l<j;++l)
    						f[i][j][k]=max(f[i][j][k],f[i][l][k-1]+s[2][j]-s[2][l]);
    					if(i==j)
    						for(int l=0;l<i;++l)
    							f[i][j][k]=max(f[i][j][k],f[l][l][k-1]+s[1][i]+s[2][i]-s[1][l]-s[2][l]);
    				}
    			}
    		printf("%d
    ",f[n][n][K]);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    【CFD之道】2018年原创文章汇总
    【OpenFOAM案例】03 Docker安装OpenFOAM
    【OpenFOAM案例】02 自己动手
    【OpenFOAM案例】01 elbow
    Fluent动网格【13】:网格光顺总结及实例
    Fluent动网格【12】:扩散光顺
    Fluent动网格【10】:区域运动案例
    Fluent动网格【11】:弹簧光顺
    happyChat开发系列:使用websocket.io实现双向通信的乐聊大前端开发
    vue,vuex的后台管理项目架子structure-admin,后端服务nodejs
  • 原文地址:https://www.cnblogs.com/cjyyb/p/7780360.html
Copyright © 2011-2022 走看看