分析:
对于网格grid[i][j]如果放向上的管道,那么grid[i][k], k>j 贪心地放向上的管道。
那么定义dp[i][j]表示第i行,最后一个放向左的管道是j的最大总矿量。
j = 0表示全放向上,j = m表示全放向左。
如果grid[i][j]要往放向上的管道的话,前提是grid[i-1][j]也要是向上的管道。
因此转移为dp[i][j] = max(dp[i-1][k]+sumA(1,j)+sumB(j+1,n) ), k >= j
对于N= 500这样的规模,转移有点慢。
对于sumA,sumB可以处理前缀和,
对于max(dp[i-1][k]),同样可以递推出来 max(dp[i-1][k]) = max(max(dp[i-1][k-1]),dp[i-1][k])
复杂度O(n*m)
窝觉得如果不是在做动态规划的专题窝可能不会往这方面去想。
#include<bits/stdc++.h> using namespace std; const int N = 501; int A[N][N], B[N][N]; int dp[N][N]; //#define LOCAL int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif int n,m; while(scanf("%d%d",&n,&m),n){ for(int i = 1; i <= n ;i++){ for(int j = 1; j <= m; j++){ scanf("%d",A[i]+j); A[i][j] += A[i][j-1]; } } for(int i = 1; i <= n ;i++){ for(int j = 1; j <= m; j++){ scanf("%d",B[i]+j); B[i][j] += B[i][j-1]; } } for(int j = 0; j <= m; j++){ dp[1][j] = A[1][j] + B[1][m] - B[1][j]; } for(int i = 2; i <= n; i++){ dp[i][0] = dp[i-1][0]; for(int j = 1; j <= m; j++){ dp[i][j] = max(dp[i][j-1],dp[i-1][j]); } for(int j = 0; j <= n; j++){ dp[i][j] += A[i][j] + B[i][m] - B[i][j]; } } int ans = 0; for(int j = 0; j <= m; j++){ ans = max(ans,dp[n][j]); } printf("%d\n",ans); } return 0; }
时间: 2024-10-13 22:17:45