• Codeforces 429B Working out(递推DP)


    题目链接:http://codeforces.com/problemset/problem/429/B

    题目大意:两个人(假设为A,B),打算健身,有N行M列个房间,每个房间能消耗Map[i][j]的卡路里,A起点为(1,1)要达到(n,m)点,且每次只能向右走一步或向下走一步,

    B起点为(n,1),要达到(1,m),且每次只能向上走一步,或向右走一步。有要求A,B必须在某一个房间相遇一次,且A,B在该房间不再消耗卡路里,因为两人锻炼身体的速度不同,

    所以在相遇时经过的房间数亦可能不相同。问两人合计最多消耗多少卡路里。

    解题思路:

    先预处理四个dp数组:

    dp1[i][j]表示从(1,1)到(n,m)路程中,(1,1)到(i,j)的最优解 

    dp2[i][j]表示从(1,1)到(n,m)路程中,(i,j)到(n,m)的最优解 

    dp3[i][j]表示从(n,1)到(1,m)路程中,(n,1)到(i,j)的最优解 

    dp4[i][j]表示从(n,1)到(1,m)路程中,(i,j)到(1,m)最优解

    由于两人只能相遇一次,若两人相遇则肯定会是以下两种情况(蓝色表示A可能经过的区域,红色表示B可能经过的区域,紫色为相遇点):

     

    那么对应上图两种情况分别有:

    t1=dp1[i][j-1]+dp2[i][j+1]+dp3[i+1][j]+dp4[i-1][j];//情况一 

    t2=dp1[i-1][j]+dp2[i+1][j]+dp3[i][j-1]+dp4[i][j+1];//情况二

    所以我们只要枚举点(i,j)即可,注意1<i<n且1<j<n否则不符合上图的情况。

    代码:

     1 #include<bits/stdc++.h>
     2 #define lc(a) (a<<1)
     3 #define rc(a) (a<<1|1)
     4 #define MID(a,b) ((a+b)>>1)
     5 #define fin(name)  freopen(name,"r",stdin)
     6 #define fout(name) freopen(name,"w",stdout)
     7 #define clr(arr,val) memset(arr,val,sizeof(arr))
     8 #define _for(i,start,end) for(int i=start;i<=end;i++)
     9 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    10 using namespace std;
    11 typedef long long LL;
    12 const int N=1e3+5;
    13 const int INF=0x3f3f3f3f;
    14 const double eps=1e-10;
    15 
    16 int mp[N][N];
    17 LL dp1[N][N],dp2[N][N],dp3[N][N],dp4[N][N];
    18 
    19 int main(){
    20     FAST_IO;
    21     int n,m;
    22     cin>>n>>m;
    23     for(int i=1;i<=n;i++){
    24         for(int j=1;j<=m;j++)
    25             cin>>mp[i][j];
    26     }
    27     //计算从(1,1)到(n,m)路程中,(1,1)到(i,j)的最优解 
    28     for(int i=1;i<=n;i++){
    29         for(int j=1;j<=m;j++){
    30             dp1[i][j]=max(dp1[i-1][j],dp1[i][j-1])+mp[i][j];
    31         }
    32     }
    33     //计算从(1,1)到(n,m)路程中,(i,j)到(n,m)的最优解 
    34     for(int i=n;i>=1;i--){
    35         for(int j=m;j>=1;j--){
    36             dp2[i][j]=max(dp2[i+1][j],dp2[i][j+1])+mp[i][j];
    37         }
    38     }
    39     //计算从(n,1)到(1,m)路程中,(n,1)到(i,j)的最优解 
    40     for(int i=n;i>=1;i--){
    41         for(int j=1;j<=m;j++){
    42             dp3[i][j]=max(dp3[i+1][j],dp3[i][j-1])+mp[i][j];
    43         }
    44     }
    45     //计算从(n,1)到(1,m)路程中,(i,j)到(1,m)最优解 
    46     for(int i=1;i<=n;i++){
    47         for(int j=m;j>=1;j--){
    48             dp4[i][j]=max(dp4[i-1][j],dp4[i][j+1])+mp[i][j];
    49         }        
    50     }
    51     
    52     LL ans=-1;
    53     //枚举相遇点,注意不能在边界相遇,因为这样两个人相遇肯定不止一次 
    54     for(int i=2;i<n;i++){
    55         for(int j=2;j<m;j++){
    56             LL t1=dp1[i][j-1]+dp2[i][j+1]+dp3[i+1][j]+dp4[i-1][j];//情况一 
    57             LL t2=dp1[i-1][j]+dp2[i+1][j]+dp3[i][j-1]+dp4[i][j+1];//情况二     
    58             ans=max(ans,max(t1,t2));
    59         }
    60     }
    61     cout<<ans<<endl;
    62     return 0;
    63 }
  • 相关阅读:
    promise请求数据(all方法)
    右键的点击事件
    微信小程序的接口调用封装
    微信小程序HTTP接口请求封装
    微信小程序得路由跳转
    管理系统得操作与解决思路
    HTTP协议
    动态语言概述
    AsynclAwait
    三种跨域解决方案
  • 原文地址:https://www.cnblogs.com/fu3638/p/9119904.html
Copyright © 2020-2023  润新知