FZU 2060 The Sum of Sub-matrices(状态压缩DP)

The Sum of Sub-matrices

Description

Seen draw a big 3*n matrix , whose entries Ai,j are all integer numbers ( 1 <= i <= 3, 1 <= j <= n ). Now he selects k sub-matrices( each Aij only belong one sub-matrices ), hoping to find the largest sum of sub-matrices’ elements.

Input

There are multiple test cases.

For each test case, the first line contains an integer n, k (1 <= n <= 100, 1 <= k <= 5, 3 * n >= k). The next three lines with n integers each gives the elements of the matrix ( | Ai,j | <= 10000).

Output

For each test case, print one line with an integer.

Sample Input

5 3

1 2 -10 3 5

3 -2 -10 2 -10

-10 -10 1 -10 -10

2 3

-1 -2

-3 -4

2 3

Sample Output

14

4

求3*n的矩阵里面的 k个子矩阵的最大和。

对列进行状态压缩

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <algorithm>

using namespace std;

typedef long long LL;
typedef pair<int,int> pii;
const int mod = 1e9+7;
const int N = 105 ;
const int M = 13;
#define X first
#define Y second

int st1[M] = { 0 , 1 , 2 , 4 , 3 , 5 , 6 , 7 , 8 , 16 , 12 , 17 , 32 };
int st2[M] = { 0 , 1 , 2 , 4 , 3 , 5 , 6 , 7 , 3 , 6 , 7 , 7 , 7 };
int num[M] = { 0 , 1 , 1 , 1 , 2 , 2 , 2 , 3 , 1 , 1 , 2 , 2 , 1 };
int A[3][N] , dp[N][6][M] , n , k ;

int Sum( int colum , int st ) {
    int res = 0 ;
    for( int i = 0 ; i < 3 ; ++i ) if( st&(1<<i) )res += A[i][colum];
    return res ;
}

void Run() {
    memset( dp , 0x80 , sizeof dp ) ;
    dp[0][0][0] = 0;

    for( int i = 0 ; i < 3 ; ++i )
        for( int j = 1 ; j <= n ; ++j )
            cin >> A[i][j];

    for( int i = 1 ; i <= n ; ++i ) {
        for( int cs = 0 ; cs < M ; ++cs ) {
            for( int ps = 0 ; ps < M ; ++ps ) {
                int w = Sum(i,st2[cs]);
                for( int k1 = 0 ; k1 <= k ; ++k1 ) {
                    int low = num[cs] , up = num[cs] ;
                    for( int z = 0 ; z < 6 ; ++z ) if( st1[cs] & st1[ps] &(1<<z) ) low--;
                    for( int k2 = low ; k1 + k2 <= k && k2 <= up ; ++k2 ){
                        dp[i][k1+k2][cs] = max( dp[i][k1+k2][cs] , dp[i-1][k1][ps] + w );
                    }
                }
            }
        }
    }
    cout << *max_element( dp[n][k] , dp[n][k]+M ) << endl ;
}

int main(){
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif // LOCAL
    ios::sync_with_stdio(false);
    while( cin >> n >> k )Run();
}

时间: 2024-10-12 11:56:04

FZU 2060 The Sum of Sub-matrices(状态压缩DP)的相关文章

HDU1565(状态压缩dp)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8170    Accepted Submission(s): 3095 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数

poj 3254 Corn Fields(状态压缩dp)

Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and

poj 2411 Mondriaan&#39;s Dream(状态压缩+dp)

 题意:用1*2砖块铺满n*m的房间. 思路转自:http://www.cnblogs.com/scau20110726/archive/2013/03/14/2960448.html 因为这道题输入范围在11*11之间,所以可以先打表直接输出.......... 状态压缩DP 经典覆盖问题,输入n和m表示一个n*m的矩形,用1*2的方块进行覆盖,不能重叠,不能越出矩形边界,问完全覆盖完整个矩形有多少种不同的方案 其中n和m均为奇数的话,矩形面积就是奇数,可知是不可能完全覆盖的.接着我们来看

Mondriaan的梦(状态压缩dp)

题目原题可以看POJ2411,大意是给出m*n的矩形,要用2*1的矩形将它铺满(不能讲一个矩形铺在另外一个上面),求方案数,并且只要不是完全相同的就算不同的方案,也就是对称算不同的方案. F[i][s]表示前i-1行已经填满,并且第i行的状态是s的方案数. F[i][s]=sum(F[i-1][s’]): s‘能转移到s.如何根据s来确定s'呢.这里用一个dfs实现,一位一位去填充s'.扫描s,如果该位是1,那么s’对应的这位必定是0,如果该位是0,那么要分情况讨论: 如果该位的后面一位也是0,

POJ 3254 【状态压缩DP】

题意: 给一块n*m的田地,1代表肥沃,0代表贫瘠. 现在要求在肥沃的土地上种草,要求任何两个草都不能相邻. 问一共有多少种种草的方法. 种0棵草也是其中的一种方法. n和m都不大于12. 思路: 状态压缩DP,dp[i][j]代表在第i行状态j一共有多少种可能的种植方法. j是二进制转化而来的状态,0代表不种草,1代表种草. dp[i]只受到两个限制,即dp[i-1]的某种状态,和当前土地的贫瘠状况. 只要保证&操作之后重复的为0就可以了 最后输出sum(dp[n][1...w])(w代表一共

ZOJ3471 状态压缩DP

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3471 Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and

HDU_2167_状态压缩dp

http://acm.hdu.edu.cn/showproblem.php?pid=2167 第一道状态压缩dp,其实就是爆搜,只不过把排除了大量不可能的情况,先用sta保存每行可能的情况,sum[i][j]保存i行j种情况的该行和,然后依次更新dp. #include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,sum[20][1<<15],dp[20][1

hdu 3217 Health(状态压缩DP)

Health Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 527    Accepted Submission(s): 145 Problem Description Unfortunately YY gets ill, but he does not want to go to hospital. His girlfriend LM

[dp专题] AC自动机与状态压缩dp的结合

最近做到好几道关于AC自动机与状态压缩dp的结合的题,这里总结一下. 题目一般会给出m个字符串,m不超过10,然后求长度为len并且包含特定给出的字符串集合的字符串个数. 以HDU 4758为例: 把题意抽象为:给出两个字符串,且只包含两种字符 'R'.'D',现在求满足下列条件的字符串个数:字符串长度为(m+n),其中包含n个'D',m个'R'. 如果不用AC自动机来做,这道题还真没法做了,因为不管怎样都找不到正确的dp状态转移方程. 而如果引入AC自动机,把在AC自动机上的结点当做dp的一个

pojPOJ 2411--Mondriaan&#39;s Dream+状态压缩dp

又是一道经典的状态压缩dp 开始自己想了一下,总是觉得因为这个小矩形可以竖着放导致没法确定状态如何转移(第i行的小矩形如果竖着放,及可能影响i-1行,也有可能影响i+1行);后面看了别人的题解后,才知道原来我们可以固定小矩形竖着放的时候只能向前放,这样第i行的状态就只能影响i-1行了,也就能顺利的写出状态转移方程啦. 设dp[i][j]表示第i行处于状态j的时候,共有多少种放置方法. dp[i][j]=sum(dp[i-1][k]),其中状态j和k要能共存,并且j和k要使得第i-1行刚好铺满.