UVALive 3530 Martian Mining(贪心,dp)

分析:

对于网格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的传递性优化

递推 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
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4853940.html