zoukankan      html  css  js  c++  java
  • 【vijos】1764 Dual Matrices(dp)

    https://vijos.org/p/1764

    自从心态好了很多后,做题的确很轻松。

    这种题直接考虑我当前拿了一个,剩余空间最大能拿多少即可。

    显然我们枚举每一个点拿出一个矩形(这个点作为右下角),然后剩余空间我们只需要考虑i+1~n和j+1~m这一块空间即可(至于为什么多想想QAQ)

    所以我们维护i+1~n和j+1~m能取到的最大矩形即可。

    显然二维前缀和,然后再维护一个二维

    mx[i][j]=max{get(i, j), mx[i+1][j], mx[i][j+1]},然后每一次找一个点i,j时只需要加上max{mx[i+1][1], mx[1][j+1]}即可。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
    #define printarr1(a, b) for1(_, 1, b) cout << a[_] << '	'; cout << endl
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=1005, oo=~0u>>2;
    int arr[N][N], sum[2][N][N], mx[N][N], n, m, a, b, ans=-oo;
    
    int get(int x, int y, int k) {
    	int ret=-oo, fx=x-(k*a)+k, fy=y-(k*b)+k, now=(k==1?0:1);
    	if(fx>=1 && fy>=1 && fx<=n && fy<=m) ret=max(ret, sum[now][x][y]-sum[now][fx-k][y]-sum[now][x][fy-k]+sum[now][fx-k][fy-k]);
    	fx=x-(k*b)+k, fy=y-(k*a)+k;
    	if(fx>=1 && fy>=1 && fx<=n && fy<=m) ret=max(ret, sum[now][x][y]-sum[now][fx-k][y]-sum[now][x][fy-k]+sum[now][fx-k][fy-k]);
    	return ret;
    }
    int main() {
    	read(n); read(m); read(a); read(b);
    	for1(i, 1, n) for1(j, 1, m) read(arr[i][j]);
    	for1(i, 1, n) for1(j, 1, m) sum[0][i][j]=sum[0][i-1][j]+sum[0][i][j-1]-sum[0][i-1][j-1]+arr[i][j];
    	for3(i, n, 1) for3(j, m, 1) sum[1][i][j]=sum[1][i+1][j]+sum[1][i][j+1]-sum[1][i+1][j+1]+arr[i][j];
    	for3(i, n+1, 0) for3(j, m+1, 0) mx[i][j]=-oo;
    	for3(i, n, 1) for3(j, m, 1) mx[i][j]=max(get(i, j, -1), max(mx[i][j+1], mx[i+1][j]));
    	for1(i, 1, n) for1(j, 1, m) ans=max(ans, get(i, j, 1)+max(mx[i+1][1], mx[1][j+1]));
    	if(ans==-oo) puts("Impossible");
    	else print(ans);
    	return 0;
    }
    

    描述

    一个N行M列的二维矩阵,矩阵的每个位置上是一个绝对值不超过1000的整数。

    你需要找到两个不相交的A*B的矩形,使得这两个矩形包含的元素之和尽量大。

    注:A*B的矩形指连续的A行、B列的子矩阵,或连续的B行、A列的子矩阵。不相交指两个矩形无公共元素。

    格式

    输入格式

    第一行包括4个正整数N,M, A, B,之间由空格隔开。

    以下N行,每行M个整数,之间由空格隔开,依次表示二维矩阵的每个元素。

    输出格式

    输出一行,一个整数,表示答案。如果找不到两个不相交的A*B的矩形,输出"Impossible"。

    样例1

    样例输入1[复制]

    3 4 1 2
    1 -1 3 4
    -1 9 -1 1
    9 8 5 2

    样例输出1[复制]

    25

    限制

    1s

    提示

    30%的数据满足,1 <= N, M <= 50.
    另外30%的数据满足,A = B.
    100%的数据满足,1 <= N, M <= 1 000, 1 <= A, B <= N.

  • 相关阅读:
    [LeetCode] Course Schedule
    [Algorithms] Topological Sort
    [Algorithms] Graph Traversal (BFS and DFS)
    [LeetCode] One Edit Distance
    [LeetCode] Summary Ranges
    [LeetCode] Missing Ranges
    [LeetCode] Fraction to Recurring Decimal
    17.Docker之使用dockerfile创建jdk镜像
    16.Docker之使用dockerfile创建nginx镜像
    7.Docker之dockerfile指令简介
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4016423.html
Copyright © 2011-2022 走看看