动规练习题

动态规划题解(数字三角形模型):

题面
某人从图中的左上角 A 出发,可以向下行走,也可以向右行走,直到到达右下角的 B 点。
在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从 A 点到 B 点共走了两次,试找出两条这样的路径,使得取得的数字和为最大。

思路
首先初步分析爆搜不行,大概率用dp来做,难点在于状态表示。类比只走一次,若只用
f[i][j]来表示状态, 则在状态转移时会遇到困难,限定了状态维数使得状态不能转移。

应该扩展状态维数使得状态转移顺利进行,即定义状态f[x1][y1][x2][y2]:第一条路径
走到(x1, y1)而第二条路径走到(x2,y2)时取走数之和的最大值,此时由于路径的最后一步
必定是向右或向下,便用分类最后一步来进行状态转移。

#include <bits/stdc++.h>

using namespace std;

int f[20][20][20][20], n, x, y, b;
int a[20][20];

int main() {
    cin >> n;
    while (cin >> x >> y >> b && x) {
        a[x][y] = b;
        
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            for (int k = 1; k <= n; k++)
                for (int l = 1; l <= n; l++) {
                    int &x = f[i][j][k][l];
                    x = max(max(f[i - 1][j][k - 1][l], f[i - 1][j][k][l - 1]), max(f[i][j - 1][k - 1][l], f[i][j - 1][k][l - 1]))
                     + a[i][j];
                    if (i != k || j != l) x += a[k][l];
                }

    cout << f[n][n][n][n] << '\n';
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值