题目链接: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 }