2017 ICPC BeiJing Regional Hihocoder 1634 Puzzle Game

来源:互联网 发布:网络监控数据线连接 编辑:程序博客网 时间:2024/06/06 17:51

简略题意:给出一个n*m的矩阵,可以修改其中一个数字为p,使得最大子矩阵的值最小化。

暴力的做法就是n*m的枚举节点,然后每次n3的求最大子矩阵。
其实没有必要,假若我们求出了最大子矩阵唯一,那么我们只要枚举最大子矩阵的一个值修改之后,再求即可。
假若最大子矩阵不唯一,那么我们还是只要枚举任意一个最大子矩阵的值即可。因为如果两个最大子矩阵的有公共部分,那么答案必然可以被枚举到。如果没有公共部分,那么怎么修改都不会改变答案。

因此我只需要枚举任意一个最大子矩阵的所有点进行修改,想办法加速新图上最大子矩阵的求解即可。
对此我们只需要预处理出每个点上/下/左/右的最大子矩阵分别是多少。
令原来图的最大子矩阵的值为ans,那么新图的最大子矩阵即为max(ans - v[i][j] + p, L, R, U, D)。
复杂度O(n3)

#define others#ifdef poj#include <iostream>#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <vector>#endif // poj#ifdef others#include <bits/stdc++.h>#endif // others//#define file#define all(x) x.begin(), x.end()using namespace std;const double eps = 1e-8;int dcmp(double x) { if(fabs(x)<=eps) return 0; return (x>0)?1:-1;};typedef long long LL;typedef unsigned long long ULL;void file() {    freopen("out.txt", "r", stdin);    freopen("out1.txt", "w", stdout);}namespace Solver {    int n, m, p;    const int maxn = 160;    int L[maxn], R[maxn], U[maxn], D[maxn];    int v[maxn][maxn];    int S[maxn][maxn];    void solve() {        while(~scanf("%d%d%d", &n, &m, &p)) {            memset(L, -0x3f3f3f3f, sizeof L);            memset(R, -0x3f3f3f3f, sizeof R);            memset(U, -0x3f3f3f3f, sizeof U);            memset(D, -0x3f3f3f3f, sizeof D);            for(int i = 1; i <= n; i++)                for(int j = 1;  j <= m; j++)                    scanf("%d", &v[i][j]), S[i][j] = S[i-1][j] + S[i][j-1] - S[i-1][j-1] + v[i][j];            int st, et;            int sx, sy, ex, ey;            int maxans = -0x3f3f3f3f;            for(int i = n; i >= 1; i--)                for(int j = i; j <= n; j++) {                    int x = 0;                    int ans = -0x3f3f3f3f;                    for(int k = 1; k <= m; k++) {                        int val = S[j][k] - S[i-1][k] - (S[j][k-1] - S[i-1][k-1]);                        if(x < 0) x = val;                        else x += val;                        ans = max(ans, x);                    }                    D[i-1] = max(D[i-1], max(D[i], ans));                    maxans = max(maxans, ans);                }            for(int i = 1; i <= n; i++)                for(int j = 1; j <= i; j++) {                    int x = 0;                    int ans = -0x3f3f3f3f;                    for(int k = 1; k <= m; k++) {                        int val = S[i][k] - S[j-1][k] - (S[i][k-1] - S[j-1][k-1]);                        if(x < 0) x = val;                        else x += val;                        ans = max(ans, x);                    }                    U[i+1] = max(U[i+1], max(U[i], ans));                }            for(int i = 1; i <= m; i++)                for(int j = 1; j <= i; j++) {                    int x = 0;                    int ans = -0x3f3f3f3f;                    for(int k = 1; k <= n; k++) {                        int val = S[k][i] - S[k][j-1] - (S[k-1][i] - S[k-1][j-1]);                        if(x < 0) x = val;                        else x += val;                        ans = max(ans, x);                    }                    L[i+1] = max(L[i+1], max(L[i], ans));                }            for(int i = m; i >= 1; i--)                for(int j = i; j <= m; j++) {                    int x = 0;                    int ans = -0x3f3f3f3f;                    for(int k = 1; k <= n; k++) {                        int val = S[k][j] - S[k][i-1] - (S[k-1][j] - S[k-1][i-1]);                        if(x < 0) x = val;                        else x += val;                        ans = max(ans, x);                    }                    R[i-1] = max(R[i-1], max(R[i], ans));                }            for(int i = 1; i <= n; i++)                for(int j = i; j <= n; j++) {                    int x = 0;                    int ans = -0x3f3f3f3f;                    st = 1;                    for(int k = 1; k <= m; k++) {                        int val = S[j][k] - S[i-1][k] - (S[j][k-1] - S[i-1][k-1]);                        if(x < 0) st = k, x = val;                        else x += val;                        if(x == maxans) {                            et = k;                            sx = i, sy = st, ex = j, ey = et;                            goto LOOP;                        }                    }                }            LOOP: ;            int fans = maxans;            for(int i = sx; i <= ex; i++)                for(int j = sy; j <= ey; j++) {                    fans = min(fans, max(maxans - v[i][j] + p, max(L[j], max(R[j], max(U[i], D[i])))));                }            cout<<fans<<endl;        }    }}int main() {//    file();    Solver::solve();    return 0;}
阅读全文
0 0
原创粉丝点击