2017 ICPC 北京站 H (hihocoder 1634) Puzzle Game (dp 最大子矩阵和)

来源:互联网 发布:油漆测哪些环保数据 编辑:程序博客网 时间:2024/05/29 18:36

解题思路:

很容易想到的是如果需要修改的话我们一定要对最大子矩阵的内部修改。不然最大值始终不变。

所以我们需要维护出最大子矩阵的位置,那么如果有多个最大子矩阵怎么办呢?维护任意一个即可。后面会说明原因。

然后枚举最大子矩阵里面的点,修改这个点我们能得到的当前矩阵的最大子矩阵和应该等于 max(上方最大子矩阵和,下方最大子矩阵和,左方最大子矩阵和,右方最大子矩阵和,包含这个点后的最大子矩阵和 利用当前最大的和维护 )

然后再来回答刚才那个问题,如果有多个最大子矩阵怎么办? 如果这个点被多个最大子矩阵包含,那么修改这个点对所有的最大子矩阵的效果等同。如果有不包含这个点的最大子矩阵,我们求这个点四周的最大子矩阵的时候会求出来。


提供一组数据
3 4 4
-2 1 3 4
5 -7 1 3
2 6 -4 1
answer: 11

AC代码:

/** @Author: wchhlbt* @Last Modified time: 2017-11-19*/#include <bits/stdc++.h>#define inf 0x3f3f3f3f#define pb push_back#define AA first#define BB second#define ONES(x) __builtin_popcount(x)#define _  << " " <<using namespace std;typedef pair<int, int> P;typedef long long ll ;int dx[4] = {0,1,0,-1};int dy[4] = {1,0,-1,0};const double eps =1e-3;const int mod = 1000000007;const double PI = acos(-1.0);inline int read(){ int num;    scanf("%d",&num);   return num;}const int maxn = 202;int a[maxn][maxn];int u[maxn][maxn];// up to downint l[maxn][maxn];// left to rightint hang[maxn][maxn];int lie[maxn][maxn];int H[maxn];int HH[maxn];int L[maxn];int LL[maxn];int dp[maxn];int n,m,p;int cal(int x, int y){    return max( max(H[x-1],HH[x+1]) , max(L[y-1],LL[y+1]));}int main(){    //cout << (inf>1e8) << endl;    //int n,m,p;    while(~scanf("%d%d%d",&n,&m,&p))    {        for(int i = 1; i<=200; i++)            for(int j = 1; j<=200; j++)                hang[i][j] = lie[i][j] = -inf;                for(int i = 1; i<=n; i++){            l[i][0] = 0;            for(int j = 1; j<=m; j++){                a[i][j] = read();                l[i][j] = a[i][j] + l[i][j-1];            }        }        for(int j = 1; j<=m; j++){            u[0][j] = 0;            for(int i = 1; i<=n; i++){                u[i][j] = a[i][j] + u[i-1][j];            }        }        int ans = -inf;        int shang,xia,zuo,you;        for(int i = 1; i<=n; i++){            for(int j = i; j<=n; j++){                dp[0] = 0;                int lp = 1;                for(int x = 1; x<=m; x++){                    int w = u[j][x] - u[i-1][x];                    if(w>=dp[x-1]+w){                        lp = x;                        dp[x] = w;                    }                    else                        dp[x] = dp[x-1] + w;                    if(dp[x]>=ans){                        ans = dp[x];                        shang = i;                        xia = j;                        zuo = lp;                        you = x;                    }                    hang[i][j] = max(hang[i][j], dp[x]);                }            }        }        int ans1 = -inf;        for(int i = 1; i<=m; i++){            for(int j = i; j<=m; j++){                dp[0] = 0;                for(int x = 1; x<=n; x++){                    int w = l[x][j] - l[x][i-1];                    dp[x] = max(dp[x-1] + w, w);                    lie[i][j] = max(lie[i][j],dp[x]);                    ans1 = max(ans1,dp[x]);                }            }        }        H[0] = -inf;        for(int i = 1; i<=n; i++){            H[i] = -inf;            for(int j = 1; j<=i; j++){                H[i] = max(H[i],hang[j][i]);            }            H[i] = max(H[i],H[i-1]);        }        HH[n+1] = -inf;        for(int i = n; i>=1; i--){            HH[i] = -inf;            for(int j = n; j>=i; j--){                HH[i] = max(HH[i],hang[i][j]);            }            HH[i] = max(HH[i],HH[i+1]);        }        L[0] = -inf;        for(int i = 1; i<=m; i++){            L[i] = -inf;            for(int j = 1; j<=i; j++){                L[i] = max(L[i],lie[j][i]);            }            L[i] = max(L[i],L[i-1]);        }        LL[m+1] = -inf;        for(int i = m; i>=1; i--){            LL[i] = -inf;            for(int j = m; j>=i; j--){                LL[i] = max(LL[i],lie[i][j]);            }            LL[i] = max(LL[i],LL[i+1]);        }        /*puts("---------------");        cout << ans _ ans1 _ shang _ xia _ zuo _ you << endl;        puts("---------------");*/        int res = ans;        for(int i = shang; i<=xia; i++){            for(int j = zuo; j<=you; j++){                if(a[i][j]>p){                    int temp = cal(i,j);                    //cout << i _ j _ temp << endl;                    res = min (res , max(temp,ans-a[i][j]+p) );                }            }        }        cout << res << endl;    }    return 0;}