zoukankan      html  css  js  c++  java
  • Codeforces Round #245 (Div. 1) B. Working out dp

    题目链接:

    http://codeforces.com/contest/429/problem/B

    B. Working out

    time limit per test2 seconds
    memory limit per test256 megabytes
    #### 问题描述 > Summer is coming! It's time for Iahub and Iahubina to work out, as they both want to look hot at the beach. The gym where they go is a matrix a with n lines and m columns. Let number a[i][j] represents the calories burned by performing workout at the cell of gym in the i-th line and the j-th column. > > Iahub starts with workout located at line 1 and column 1. He needs to finish with workout a[n][m]. After finishing workout a[i][j], he can go to workout a[i + 1][j] or a[i][j + 1]. Similarly, Iahubina starts with workout a[n][1] and she needs to finish with workout a[1][m]. After finishing workout from cell a[i][j], she goes to either a[i][j + 1] or a[i - 1][j]. > > There is one additional condition for their training. They have to meet in exactly one cell of gym. At that cell, none of them will work out. They will talk about fast exponentiation (pretty odd small talk) and then both of them will move to the next workout. > > If a workout was done by either Iahub or Iahubina, it counts as total gain. Please plan a workout for Iahub and Iahubina such as total gain to be as big as possible. Note, that Iahub and Iahubina can perform workouts with different speed, so the number of cells that they use to reach meet cell may differs. #### 输入 > The first line of the input contains two integers n and m (3 ≤ n, m ≤ 1000). Each of the next n lines contains m integers: j-th number from i-th line denotes element a[i][j] (0 ≤ a[i][j] ≤ 105). #### 输出 > The output contains a single number — the maximum total gain possible. #### 样例 > **sample input** > 3 3 > 100 100 100 > 100 1 100 > 100 100 100 > > **sample output** > 800

    题意

    每个点有a[i][j]的物品(非负数),现在有一个人要从(1,1)到(n,m),且只能往下或者往右走,另一个人从(n,1)->(1,m),且只能往上或往右走,现在要让这两个人的路线有且只有一个公共点(且公共点的物品谁都不能取),问如何规划使得两个人能够获得的物品总数最多。

    题解

    这题比较特殊的地方在公共点,从公共点(x,y)出发,你会发现我们把原问题划分成了四个简单的子问题:(1,1)->(x,y),(n,1)->(x,y),(n,m)->(x,y),(1,m)->(x,y),但是你发现枚举这个点是不够的,还需要枚举这个点的上下左右四个点(既如何安排这两个人进入x,y的入口,使得刚好能够只有(x,y)这一个公共点)

    代码

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=0x3f3f3f3f3f3f3f3fLL;
    const double eps=1e-8;
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    const int maxn=1e3+10;
    
    int arr[maxn][maxn];
    int dp[4][maxn][maxn];
    int n,m;
    
    void init(){
        clr(dp,0);
    }
    
    int main() {
        scf("%d%d",&n,&m);
        init();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scf("%d",&arr[i][j]);
            }
        }
        //(1,1)->(n,m)
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                dp[0][i][j]=max(dp[0][i-1][j],dp[0][i][j-1])+arr[i][j];
            }
        }
        //(n,1)->(1,m)
        for(int i=n;i>=1;i--){
            for(int j=1;j<=m;j++){
                dp[1][i][j]=max(dp[1][i][j-1],dp[1][i+1][j])+arr[i][j];
            }
        }
        //(n,m)->(1,1)
        for(int i=n;i>=1;i--){
            for(int j=m;j>=1;j--){
                dp[2][i][j]=max(dp[2][i+1][j],dp[2][i][j+1])+arr[i][j];
            }
        }
        //(1,m)->(n,1)
        for(int i=1;i<=n;i++){
            for(int j=m;j>=1;j--){
                dp[3][i][j]=max(dp[3][i-1][j],dp[3][i][j+1])+arr[i][j];
            }
        }
    
        int ans=-1;
        //枚举相遇点
        for(int i=2;i<n;i++){
            for(int j=2;j<m;j++){
                ans=max(ans,dp[0][i-1][j]+dp[2][i+1][j]+dp[1][i][j-1]+dp[3][i][j+1]);
                ans=max(ans,dp[0][i][j-1]+dp[2][i][j+1]+dp[1][i+1][j]+dp[3][i-1][j]);
            }
        }
    
        printf("%d
    ",ans);
        return 0;
    }
    
    //end-----------------------------------------------------------------------
  • 相关阅读:
    BZOJ 2456 mode
    BZOJ 1041 [HAOI2008]圆上的整点
    东北育才 第6天和第7天
    POJ 3692 Kindergarten(最大团问题)
    KM算法及其应用
    UVA 11582 Colossal Fibonacci Numbers!(循环节打表+幂取模)
    ZOJ 3960 What Kind of Friends Are You?(读题+思维)
    POJ 2349 Arctic Network(最小生成树中第s大的边)
    HDU 1576 A/B(欧几里德算法延伸)
    NYOJ 1013 除法表达式(欧几里德算法+唯一分解定理)
  • 原文地址:https://www.cnblogs.com/fenice/p/5834188.html
Copyright © 2011-2022 走看看