zoukankan      html  css  js  c++  java
  • BZOJ 1084: [SCOI2005]最大子矩阵( dp )

    最多只有2列..分开来dp

    1列 dp(x, k) = max( dp(x - 1, k), dp(p, k - 1) + sum(p+1~x) ) 

    2列 dp(a, b, k) = max( dp(a - 1, b, k), dp(a, b - 1, k), dp(p, b, k - 1) + sum1(p+1~a), dp(a, p, k - 1) + sum2(p+1~b) ) 当a = b, dp(a, b, k)还可以用dp(p, p, k - 1) + SUM(p+1~a) (0 ≤ p < a)更新

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int maxk = 19;
    const int maxn = 109;
    
    int N, K;
    
    namespace one {
    	int sum[maxn], dp[maxn][maxk];
    	void init() {
    		sum[0] = 0;
    		for(int i = 1; i <= N; i++) {
    		    scanf("%d", sum + i);
    		    sum[i] += sum[i - 1];
    		}
    	}
    	void work() {
    		init();
    		memset(dp, 0, sizeof dp);
    		for(int i = 0; i < N; i++) {
    			for(int k = 0; k <= K; k++) 
    			    dp[i + 1][k] = max(dp[i + 1][k], dp[i][k]);
    			for(int k = 1; k <= K; k++)
    			    for(int j = i + 1; j <= N; j++)
    			        dp[j][k] = max(dp[j][k], dp[i][k - 1] + sum[j] - sum[i]);
    		}
    		printf("%d
    ", dp[N][K]);
    	}
    }
    
    namespace two {
    	int sum[2][maxn], dp[maxn][maxn][maxk];
    	void init() {
    		sum[0][0] = sum[1][0] = 0;
    		for(int j = 1; j <= N; j++)
    		    for(int i = 0; i < 2; i++) {
    		    	scanf("%d", &sum[i][j]);
    		    	sum[i][j] += sum[i][j - 1];
    		    }
    	}
    	void work() {
    		init();
    		memset(dp, 0, sizeof dp);
    		for(int i = 0; i <= N; i++)
    	        for(int j = 0; j <= N; j++) if(i + j < N * 2) {
    	            for(int k = 0; k <= K; k++) {
    	            	if(i < N) dp[i + 1][j][k] = max(dp[i + 1][j][k], dp[i][j][k]);
    	            	if(j < N) dp[i][j + 1][k] = max(dp[i][j + 1][k], dp[i][j][k]);
    	            }
    	            for(int k = 1; k <= K; k++)
    	                for(int _i = i; _i <= N; _i++)
    	                    for(int _j = j; _j <= N; _j++) if(_i + _j > i + j) {
    	                        dp[_i][_j][k] = max(dp[_i][_j][k], dp[i][_j][k - 1] + sum[0][_i] - sum[0][i]);
    	                        dp[_i][_j][k] = max(dp[_i][_j][k], dp[_i][j][k - 1] + sum[1][_j] - sum[1][j]);
    	                    }
    	            if(i == j) {
    	            	for(int k = 0; k <= K; k++)
    	            	    dp[i + 1][j + 1][k] = max(dp[i + 1][j + 1][k], dp[i][j][k]);
    	            	for(int _i = i + 1; _i <= N; _i++)
    	            	    for(int k = 1; k <= K; k++)
    	            	        dp[_i][_i][k] = max(dp[_i][_i][k], dp[i][j][k - 1] + sum[0][_i] - sum[0][i] + sum[1][_i] - sum[1][j]);
    	            }
    	        }
    	    printf("%d
    ", dp[N][N][K]);
    	}
    }
    
    int main() {
    	
    	int m;
    	cin >> N >> m >> K;
    	m == 1 ? one::work() : two::work();
    	
    	return 0;
    }
    

      

    1084: [SCOI2005]最大子矩阵

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1614  Solved: 821
    [Submit][Status][Discuss]

    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

    HINT

     

    Source

     

  • 相关阅读:
    【H5】01 入门 & 概述
    【Mybatis + Spring】 Mybatis
    【Mybatis】Bonus01 笔记资料
    【Spring】06 Aop切面功能
    【Spring】05 注解开发
    【Spring】04 注解实现自动装配
    【Spring】03 XML配置
    【Spring】02 过程分析
    【Mybatis】11 注解的使用
    【Mybatis】10 实现分页 & 分页插件
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4732568.html
Copyright © 2011-2022 走看看