CodeForces 429 B Working out(递推dp)
题目连接:B. Working out
我想了很久都没有想到怎么递推,看了题解后试着自己写,结果第二组数据就 wa 了,后来才知道自己没有判选择的两条路径是否只是一个交点。
大概思路是:先预处理出每个格子到四个角落格子的路径最大数值,然后枚举两个人相遇的交点格子,枚举 A、B 的进来和出去方式(记两个线路为 1 和 2,考虑一个公共点,1 为左进右出,2 为下进上出;1 上进下出,2 为左进右出),然后求最大值即可。
注意边界情况。
原题解链接:http://blog.csdn.net/cc_again/article/details/25691925, http://blog.csdn.net/qq574857122/article/details/25625151
我的代码:(全用宏定义了 -_-|| )
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define sd(x) scanf("%d",&(x)) 6 #define sd2(x,y) scanf("%d %d",&(x),&(y)) 7 typedef long long LL; 8 9 LL dp[5][1003][1003], a[1003][1003]; 10 11 #define For(i,s,t) for(int i = s; i <= t; ++i) 12 #define desFor(i,t,s) for(int i = t; i >= s; --i) 13 14 int main() { 15 int n,m; 16 while(~sd2(n,m)) { 17 For(k,1,4) For(i,0,n+1) 18 dp[k][i][m + 1] = 0; 19 For(k,1,4) For(j,0,m+1) 20 dp[k][n + 1][j] = 0; 21 For(i,1,n) For(j,1,m) 22 sd(a[i][j]); 23 // 递推预处理出所有交点到 4 个角的最大值 24 For(i,1,n) For(j,1,m) 25 dp[1][i][j] = max(dp[1][i-1][j], dp[1][i][j-1]) + a[i][j]; 26 For(i,1,n) desFor(j,m,1) 27 dp[2][i][j] = max(dp[2][i-1][j], dp[2][i][j+1]) + a[i][j]; 28 desFor(i,n,1) For(j,1,m) 29 dp[3][i][j] = max(dp[3][i+1][j], dp[3][i][j-1]) + a[i][j]; 30 desFor(i,n,1) desFor(j,m,1) 31 dp[4][i][j] = max(dp[4][i+1][j], dp[4][i][j+1]) + a[i][j]; 32 LL ans = 0; 33 // 枚举所有交点 34 For(i,2,n-1) For(j,2,m-1) { 35 // 第一种路径选择: A 从上往下穿过交点 dp[i][j],B 从左向右穿过 dp[i][j] 36 LL first = dp[1][i-1][j] + dp[4][i+1][j] + dp[2][i][j+1] + dp[3][i][j-1]; 37 ans = max(ans, first); 38 // 第二种路径选择: A 从左向右穿过交点 dp[i][j],B 从上往下穿过 dp[i][j] 39 LL second = dp[1][i][j-1] + dp[4][i][j+1] + dp[2][i-1][j] + dp[3][i+1][j]; 40 ans = max(ans, second); 41 } 42 printf("%I64d\n",ans); 43 } 44 return 0; 45 }