P1004 [NOIP2000 提高组] 方格取数 - 四维dp

方格取数原题链接icon-default.png?t=M276https://www.luogu.com.cn/problem/P1004        通过题意我们可以可以看出这是一道动态规划的题,第一想法是用二维的话只能dp出最大值的路径,再用一次二维dp求出次大值的路径,这样的想法是错误的!题目要求的是两条路径走到右下角的和的最大值!如果是按照刚刚的想法,先求最大值的路径,再求次大值的路径,最大值确实是最大值,但是次大值就不一定了,为了走出最大值就不得不让次大值小。可以自己举个例子看看。

        也就是说这两步不能分成两次规划,要让和的最大值在一个规划中约束两条路径的生成。那么怎么在一个动态规划中表示两条路径呢,我们用二维只能表示一条,那我们再用两个纬度来表示第二条路径不就好了吗?这样四维状态方程也就被构想出来了。即,我们用f[i][j][k][l]作为状态方程,表示第一个人走到(i,j)时,第二个人走到(k,l),f[i][j][k][l]表示的是取到物品的价值和的最大值。

        怎么表示状态转移呢?两个人从同一起点出发,每个人都有两种方向可以走,那么两个人就有四种方向:

  • 第一个人向右,第二个人向下
  • 两个都向右
  • 第一个人向下,第二个人向右
  • 两个人都向下

也就是从要走到(i,j)和(k,l)有上述四个方法,那么状态转移就表示为从上述四个方向来的和的最大值加上(i,j)和(k,l)上的物品的价值:

f[i][j][k][l] = max(max(f[i][j - 1][k][l - 1], f[i][j - 1][k - 1][l]), max(f[i - 1][j][k][l - 1], f[i - 1][j][k - 1][l])) + a[i][j] + a[k][l];

最终的答案就是:f[n][n][n][n],两个人都走到了右下角

这里要注意:当第一个人和第二个人走到了同一个点时,也就是i==k,j==l,因为物品只有一个,被一个人捡走了就没了,所以要特判一下,减去状态转移方程中多加的一个

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 10;

int a[N][N], f[N][N][N][N];
int n, u, v, w;

int main()
{
    cin >> n;
    while (cin >> u >> v >> w)
    {
        if (!u && !v && !w)
            break;
        a[u][v] = w;
    }

    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++)
                {
                    f[i][j][k][l] = max(max(f[i][j - 1][k][l - 1], f[i][j - 1][k - 1][l]), max(f[i - 1][j][k][l - 1], f[i - 1][j][k - 1][l])) + a[i][j] + a[k][l];
                    if (i == k && j == l)
                        f[i][j][k][l] -= a[i][j];
                }

    cout << f[n][n][n][n];
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linengcs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值