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


    题目描述

    思路分析

    错误思路:

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

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

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

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

    起初,我们很容易想到用四维数组表示状态f[i1][j1][i2][j2]

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

    下面对集合进行划分:

    对于f[k][i1][i2],包含四部分:

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

    第二部分是第一条路从右边走过来,第二条路是从上面走过来 f[k-1][i1][i2-1]+t

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

    第四部分是第一条路从右边走过来,第二条路是从右面走过来 f[k-1][i1][i2]+t

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

    i1==i2   t=w[i1][k-i1]

    i1!=i2    t=w[i1][k-i1]+w[i2][k-i2]

    最后答案即为:f[n+n][n][n]

    1. #include
    2. using namespace std;
    3. const int N=15;
    4. int f[N*2][N][N];
    5. int w[N][N];
    6. int n;
    7. int main()
    8. {
    9. scanf("%d",&n);
    10. int a,b,c;
    11. while(cin>>a>>b>>c,a||b||c)w[a][b]=c;
    12. for(int k=2;k<=n*2;k++)
    13. {
    14. for(int i1=1;i1<=n;i1++)
    15. {
    16. for(int i2=1;i2<=n;i2++)
    17. {
    18. int j1=k-i1,j2=k-i2;
    19. if(j1>=1&&j1<=n&&j2>=1&&j2<=n)
    20. {
    21. int t=w[i1][j1];
    22. if(i1!=i2)t+=w[i2][j2];
    23. int &x=f[k][i1][i2];
    24. x=max(x,f[k-1][i1-1][i2-1]+t);
    25. x=max(x,f[k-1][i1-1][i2]+t);
    26. x=max(x,f[k-1][i1][i2-1]+t);
    27. x=max(x,f[k-1][i1][i2]+t);
    28. }
    29. }
    30. }
    31. }
    32. cout<2*n][n][n];
    33. return 0;
    34. }

  • 相关阅读:
    C++代码示例:进制数简单生成工具
    EasyCVR平台设备在线,播放视频却提示离线是什么原因?
    《nginx》四、nginx的负载均衡 + keepalived实现nginx的高可用
    区间统计——ST算法
    HarmonyOS—LocalStorage:页面级UI状态存储
    梳理市面上的2大NFT定价范式和4种解决方案
    【论文笔记】DeepLab系列
    Redis实现简易消息队列的三种方式
    [论文阅读](Objective Quality Evaluation of Dehazed Images)
    什么是产品主导的增长以及为什么它对 API 优先的公司至关重要
  • 原文地址:https://blog.csdn.net/m0_63222058/article/details/133246369