zoukankan      html  css  js  c++  java
  • Sgu167 I-country

    题目描述

    在 N*M 的矩阵中,每个格子有一个权值,要求寻找一个包含 K 个格子的凸连通块(连通块中间没有空缺,并且轮廓是凸的,如右图所示),使这个连通块中的格子的权值和最大。求出这个最大的权值和.N,M≤15,K≤225。

    输入格式

    第一行给出N,M,K,接下来给出这个矩阵

    输出格式

    如题


    首先我们要明确凸连通块是什么:

    它是一个连通块。从上往下看,它的左端点下标先递减后递增,右端点下标先递增后递减。

    根据这一点,我们能够设计出这样的状态:

    设dp(i,j,l,r,0/1,0/1)表示当前为第i行,已经用了j个格子,凸连通块在第i行的左端点为l,右端点为r,左端点现在在递增(0)还是递减(1),右端点在递增(0)还是递减(1)。那么可以列出状态转移方程:

    [len=r-l+1\ dp[i][j][l][r][1][0]=sum_{p=l}^{r}a[i][p]+Max_{l≤p≤q≤r}{{}dp[i-1][j-len][p][q][1][0]{}}\ dp[i][j][l][r][1][1]=sum_{p=l}^{r}a[i][p]+Max_{l≤p≤r≤q}{{}Max_{0≤y≤1}{{}dp[i-1][j-len][p][q][1][y]{}}{}}\ dp[i][j][l][r][0][0]=sum_{p=l}^{r}a[i][p]+Max_{p≤l≤q≤r}{{}Max_{0≤x≤1}{{}dp[i-1][j-len][p][q][x][0]{}}{}}\ dp[i][j][l][r][0][1]=sum_{p=l}^{r}a[i][p]+Max_{p≤l≤r≤q}{{}Max_{0≤x≤1}{{}Max_{0≤y≤1}{{}dp[i-1][j-len][p][q][x][y]{}}{}}{}} ]

    初始化都为0,目标状态:Max{dp(i,K,l,r,x,y)}。

    时间复杂度为O(N * M^4 * K)

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define maxn 16
    #define maxm 226
    using namespace std;
     
    int dp[maxn][maxm][maxn][maxn][2][2];
    int n,m,sum,val[maxn][maxn];
    int ans;
     
    inline int read(){
        register int x(0),f(1); register char c(getchar());
        while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
        while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
     
    int main(){
        n=read(),m=read(),sum=read();
        for(register int i=1;i<=n;i++){
            for(register int j=1;j<=m;j++) val[i][j]=val[i][j-1]+read();
        }
     
        for(register int i=1;i<=n;i++){
            for(register int j=1;j<=sum;j++){
                for(register int l=1;l<=m;l++){
                    for(register int r=l;r<=m;r++){
                        if(j<r-l+1) break;
                        for(register int p=l;p<=r;p++){
                            for(register int q=p;q<=r;q++){
                                dp[i][j][l][r][1][0]=max(dp[i][j][l][r][1][0],dp[i-1][j-(r-l+1)][p][q][1][0]+val[i][r]-val[i][l-1]);
                            }
                        }
                        for(register int p=l;p<=r;p++){
                            for(register int q=r;q<=m;q++){
                                dp[i][j][l][r][1][1]=max(dp[i][j][l][r][1][1],max(dp[i-1][j-(r-l+1)][p][q][1][0],dp[i-1][j-(r-l+1)][p][q][1][1])+val[i][r]-val[i][l-1]);
                            }
                        }
                        for(register int p=1;p<=l;p++){
                            for(register int q=l;q<=r;q++){
                                dp[i][j][l][r][0][0]=max(dp[i][j][l][r][0][0],max(dp[i-1][j-(r-l+1)][p][q][0][0],dp[i-1][j-(r-l+1)][p][q][1][0])+val[i][r]-val[i][l-1]);
                            }
                        }
                        for(register int p=1;p<=l;p++){
                            for(register int q=r;q<=m;q++){
                                dp[i][j][l][r][0][1]=max(dp[i][j][l][r][0][1],max(dp[i-1][j-(r-l+1)][p][q][0][1],max(dp[i-1][j-(r-l+1)][p][q][1][0],max(dp[i-1][j-(r-l+1)][p][q][1][1],dp[i-1][j-(r-l+1)][p][q][0][0])))+val[i][r]-val[i][l-1]);
                            }
                        }
                        if(j==sum) ans=max(ans,max(dp[i][j][l][r][0][0],max(dp[i][j][l][r][1][0],max(dp[i][j][l][r][0][1],dp[i][j][l][r][1][1]))));
                    }
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    css 透明气泡效果
    uniapp 跳转tabbar页面传递参数
    unaipp 发送验证码倒计时
    uniapp 返回顶部
    js 实现放大镜效果
    js 禁用右键菜单和禁止复制
    js 表格的添加和删除操作
    js 留言板(带删除功能)
    推荐几个好用的网站
    pc端使用rem适配
  • 原文地址:https://www.cnblogs.com/akura/p/11045518.html
Copyright © 2011-2022 走看看