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 }

 

posted @ 2018-06-01 02:12  Yeader  阅读(288)  评论(0编辑  收藏  举报