• Codeforces1304F.Animal Observation


    分析一下得知是DP问题,时间复杂度符合,设dp[i][j]为从第i天开始,第j个位置能得到的最大值,其有三种转移状态

    1.与上一天的选择有重合

    2.与上一天的选择没有重合,且上一天的选择在左边

    3.与上一天的选择没有重合,且上一天的选择在右边

    那么得到转移方程,

    1.dp[i][j] = max(dp[i-1][x])(x+k-1与j+k-1有交点)-重复部分

    2.dp[i][j] = max(dp[i-1][x])(x+k-1在j的左边)+该次选择得到的数

    3.同2

    我们预处理前缀和,再在每次dp更新后为下一天的dp更新每个点左边的最大值,复杂度为O(nmk)

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) ((x)&(-x))
    typedef long long LL;
    
    const int maxn = 55;
    const int maxm = 2e4+5;
    
    int dp[maxn][maxm], C[maxn][maxm], lmax[maxn][maxm], rmax[maxn][maxm];
    
    int getsum(int i, int p1, int p2) {
        return C[i][p2] - C[i][p1-1];
    }
    
    
    void run_case() {
        int n, m, k, val;
        cin >> n >> m >> k;
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j) {
                cin >> val;
                C[i][j] = C[i][j-1] + val;
            }
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= m - k + 1; ++j) {
                val = getsum(i, j, j+k-1) + getsum(i+1, j, j+k-1);
                if(i == 1) {
                    dp[i][j] = val;
                    continue;
                }
                int mx = 0;
                // intersect part
                for(int l = max(1, j-k+1); l <= min(m-k+1, j+k-1); ++l)
                    mx = max(mx, dp[i-1][l]+val-getsum(i, max(l, j), min(j+k-1,l+k-1)));
                dp[i][j] = mx;
                if(j > k) dp[i][j] = max(dp[i][j], lmax[i-1][j-k]+val);
                if(j + k <= m - k + 1) dp[i][j] = max(dp[i][j], rmax[i-1][j+k]+val);
            }
            for(int j = 1; j <= m-k+1; ++j) lmax[i][j] = max(dp[i][j], lmax[i][j-1]);
            for(int j = m-k+1; j >= 1; --j) rmax[i][j] = max(dp[i][j], rmax[i][j+1]);
        }
        cout << *max_element(dp[n]+1, dp[n]+1+m) << "
    ";
    }
     
    int main() {
        ios::sync_with_stdio(false), cin.tie(0);
        //cout.setf(ios_base::showpoint);cout.precision(10);
        //int t; cin >> t;
        //while(t--)
        run_case();
        cout.flush();
        return 0;
    }
    View Code

    hard vision就是将k的范围扩大很多,可以用线段树O(nmlogm)或者是单调队列O(nm)来优化区间最值问题,以后再补

  • 相关阅读:
    androidlayout_weight的使用
    软件开发中的真理.
    apk,task,android:process与android:sharedUserId的区别
    WIFI连接
    go simple web server
    echo命令
    shell if
    linux grep命令(包括正则)
    make命令和Makefile文件
    linux中grep命令的用法
  • 原文地址:https://www.cnblogs.com/GRedComeT/p/12317333.html
Copyright © 2020-2023  润新知