挖矿

https://acm.uestc.edu.cn/problem/wa-kuang-gong-lue/description

挖矿_第1张图片

挖矿_第2张图片

挖矿_第3张图片

 

• 这题有个很有噱头的分类,棋盘dp。

• 但其实就是一道最普通的dp题:找出 转移方程,结束。

• 设f[i][j] 为(1,1)到(i,j) 的子矩阵中的 最大采矿量,由题意我们可知,如果 点(i,j) 的传送带向左,那么点(i,j−1) 及其左边一定是向左,同理,如果(i,j) 的传送带向上,那么点(i−1,j)及其上 边的点,一定也是向上。 

可能对于为什么(i,j)点往左的会决定 (i,j-1)以及左边的点全部往左,我们这么 思考一下: 左 现在,我们思考,要把最右下角的输送 到左边,请问,你能想出哪些输送的方 法呢?注意,只有往左或是往上的输送 带。  左 左 上 上 左 上 左 发现了吗?当右下角这个点想输送到左边 ,必然存在从他一直连接到第一列的向左 输送的传送带,哪怕它左边的一些点选择 了向上,也逃脱不了向左的结果,而且你 有往上的,那往上的左边也一起被带着往 左了。那么,我们直接对于(i,j)向左时,它 左边的全向左,被固定向左的点就最少, 也就可以更优地决策。 

• 例如在f[2][3]的状态下,你可以向 f[3][3]转移,那么新添的第三行显然 全向西运输最优。或者向f[2][4]转移, 那么新添的第4列应该向北运输最优。 • 于是我们可以用前缀和去维护一段区 间的采矿量。 

• 转移方程:

• F[i][j]= max(f[i-1][j]+H[i][j], f[i][j-1]+S[i][j]) 具体意义和代码实现请自己动脑

(题解是直接复制粘贴的,代码是自己写)

#include 

using namespace std;
typedef long long ll;

int a[509][509];
int b[509][509];

ll nn[509][509],mm[509][509],dp[509][509];

int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&b[i][j]);
        }
    }
    for(int j=1;j<=m;j++){
        for(int i=1;i<=n;i++){
            nn[i][j]=nn[i-1][j];
            nn[i][j]=nn[i][j]+b[i][j];

            mm[i][j]=mm[i][j-1];
            mm[i][j]=mm[i][j]+a[i][j];
        }
    }

//    for(int i=1;i<=n;i++){
//        for(int j=1;j<=m;j++){
//            cout<

 

你可能感兴趣的:(dp动态规划)