【Acwing1027】方格取数(动态规划)题解

题目描述

思路分析

错误思路:

贪心法,先走一次求出最大值,把走过的路上面的数值清零,然后用同样的方法再走一遍求最大值,然后让这两个最大值相加就是最后的结果。

很多人在看到这个题目的时候会有上面的思路,但实践告诉我们,有些数据用上述思路答案是错误的,这是为什么呢?

原因很简单:假设第一次走的时候,有多条路径s1,s2,......可以得到最大值,我们并不知道要选择哪一条,也就是说我们并不知道要把哪一条路上面的数清零,因为不同的选择会对第二次走的结果产生影响!!!

所以要使用其它思路,此处采用动态规划解决

起初,我们很容易想到用四维数组表示状态fi1j1i2j2

但其实没有必要,因为我们只需要两条路"同时走"就可以了,也就是说我们可以设置一个维度代表(x,y方向上已经走的路径的和),这个表示为k,那么状态就可以降成三维:fki1i2

下面对集合进行划分:

对于fki1i2,包含四部分:

第一部分是第一条路从上边走过来,第二条路是从上面走过来 fk-1i1-1i2-1+t

第二部分是第一条路从右边走过来,第二条路是从上面走过来 fk-1i1i2-1+t

第三部分是第一条路从上边走过来,第二条路是从右面走过来 fk-1i1-1i2+t

第四部分是第一条路从右边走过来,第二条路是从右面走过来 fk-1i1i2+t

那么这个t,怎么求,就要看i1和i2是否相同了,因为如果相同的话,再走到这里值已经清空了:

i1==i2 t=wi1k-i1

i1!=i2 t=wi1k-i1+wi2k-i2

最后答案即为:fn+nnn

cpp 复制代码
#include<iostream>
using namespace std;
const int N=15;
int f[N*2][N][N];
int w[N][N];
int n;
int main()
{
    scanf("%d",&n);
    int a,b,c;
    while(cin>>a>>b>>c,a||b||c)w[a][b]=c;
    for(int k=2;k<=n*2;k++)
    {
        for(int i1=1;i1<=n;i1++)
        {
            for(int i2=1;i2<=n;i2++)
            {
                int j1=k-i1,j2=k-i2;
                if(j1>=1&&j1<=n&&j2>=1&&j2<=n)
                {
                    int t=w[i1][j1];
                    if(i1!=i2)t+=w[i2][j2];
                    int &x=f[k][i1][i2];
                    x=max(x,f[k-1][i1-1][i2-1]+t);
                    x=max(x,f[k-1][i1-1][i2]+t);
                    x=max(x,f[k-1][i1][i2-1]+t);
                    x=max(x,f[k-1][i1][i2]+t);
                }
            }
        }
    }
    cout<<f[2*n][n][n];
    return 0;
}
相关推荐
微尘hjx5 小时前
【ByteTrack 04】多轨迹算法ByteTrack改进点
算法·yolo·目标检测·目标跟踪·bytetrack·ultralytics·车跟踪
dtq04246 小时前
C++小案例 - 日志实战
开发语言·c++
码匠许师傅7 小时前
【C++三方组件】Qt 概览:桌面 C++ 的事实标准与许可证三轨
开发语言·c++·qt
码匠许师傅8 小时前
【C++三方组件】POCO:跨平台系统编程全家桶
开发语言·c++
小蒋观天下9 小时前
雷击与浪涌防护:前端SPD选型、接地网误区,接地不当反而引入干扰
深度学习·算法·机器学习
WBluuue10 小时前
数据结构与算法:分块(一):块状数组、块状链表
数据结构·c++·算法·链表
澳鹏Appen12 小时前
澳鹏重磅发布ExamOCRBench:面向端到端试卷判分的多任务基准
算法·benchmark·基准评测
必须得开心呀12 小时前
字节序大小端科普
c++·程序人生
benjormin12 小时前
Java数据结构 二叉搜索树
数据结构·算法