当前位置:   article > 正文

DP数字三角形模型_数字三角形闫氏dp

数字三角形闫氏dp

数字三角形模板题目

数字三角形

练习题目连接

1.​​​​​​摘花生

2.最低通行费用

3.方格取数

4.传字条

 数字三角形模型解题思路

根据闫氏DP分析法可以得出

根据不同的属性得到状态转移方程即可

习题代码

1.摘花生

状态转移方程f[i,j]=max(f[i-1][j]+w[i][j],f[i-1][j]+w[i][j];

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=110;
  4. int w[N][N];
  5. int f[N][N];
  6. int main()
  7. {
  8. int t;
  9. scanf("%d",&t);
  10. while(t--)
  11. {
  12. memset(f,0,sizeof f);
  13. int n,m;
  14. scanf("%d%d",&n,&m);
  15. for(int i=1;i<=n;i++)
  16. for(int j=1;j<=m;j++)
  17. scanf("%d",&w[i][j]);
  18. for(int i=1;i<=n;i++)
  19. for(int j=1;j<=m;j++)
  20. f[i][j]=max(f[i-1][j]+w[i][j],f[i][j-1]+w[i][j]);
  21. printf("%d\n",f[n][m]);
  22. }
  23. return 0;
  24. }

2.通行费用

这题多了一个数学背景商人必须在2*n-1的时间完成行走,意味着他是不可以走回头路的,得到性质以后就是摘花生问题的变形

状态转移方程同摘花生 但是变为求min

由于是求最小值,所以边界会有一些特判

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=110;
  4. int f[N][N];
  5. int w[N][N];
  6. int main()
  7. {
  8. int n;
  9. scanf("%d",&n);
  10. for(int i=1;i<=n;i++)
  11. for(int j=1;j<=n;j++)
  12. scanf("%d",&w[i][j]);
  13. for(int i=1;i<=n;i++)
  14. for(int j=1;j<=n;j++)
  15. {
  16. if(i==1&&j==1) f[i][j]=w[i][j];
  17. else
  18. {
  19. f[i][j]=0x3f3f3f3f;
  20. ///特判第一行和第一列
  21. if(i>1) f[i][j]=min(f[i][j],f[i-1][j]+w[i][j]);
  22. if(j>1) f[i][j]=min(f[i][j],f[i][j-1]+w[i][j]);
  23. }
  24. }
  25. printf("%d\n",f[n][n]);
  26. return 0;
  27. }

3.放格取数

同样是变形 是同时去走两条不同路

状态方程变为f[i1,j1,i1,j2] 四维太多考虑优化

因为只有i1+j1=i2+j2相同时,两个点才会有可能重合 所以可以设k=i1+j1=i2+j2

则方程可以优化为f[k,i1,i2]表示从起点开始分别走到(i1,k-i1)和(i2,k-i2)的路线

特判只有i1=i2时,路线才会相同(走过的点收益清零)

状态转移方程看代码

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=12;
  4. int f[N+N][N][N];
  5. int w[N][N];
  6. int n;
  7. int main()
  8. {
  9. while(scanf("%d",&n)!=EOF)
  10. {
  11. memset(f,0,sizeof f);
  12. memset(w,0,sizeof w);
  13. int a,b,c;
  14. while(scanf("%d%d%d",&a,&b,&c))
  15. {
  16. if((!a)&&(!b)&&(!c))
  17. {
  18. break;
  19. }
  20. w[a][b]=c;
  21. }
  22. for(int k=2;k<=n+n;k++)
  23. for(int i=1;i<=n;i++)
  24. for(int j=1;j<=n;j++)
  25. {
  26. int l=k-i,m=k-j;
  27. if(l>=1&&l<=n&&m>=1&&m<=n)///判断合法范围
  28. {
  29. int t=w[i][k-i];
  30. if(i!=j) t+=w[j][k-j];///路径相同有一次的点收益为0
  31. ///状态转移方程
  32. f[k][i][j]=max(f[k][i][j],f[k-1][i-1][j-1]+t);
  33. f[k][i][j]=max(f[k][i][j],f[k-1][i-1][j]+t);
  34. f[k][i][j]=max(f[k][i][j],f[k-1][i][j-1]+t);
  35. f[k][i][j]=max(f[k][i][j],f[k-1][i][j]+t);
  36. }
  37. }
  38. printf("%d\n",f[n+n][n][n]);
  39. }
  40. return 0;
  41. }

4.传纸条

与3一样

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N=55;
  4. int n,m;
  5. int f[N+N][N][N];
  6. int w[N][N];
  7. int main()
  8. {
  9. while(scanf("%d%d",&n,&m)!=EOF)
  10. {
  11. memset(f,0,sizeof f);
  12. memset(w,0,sizeof w);
  13. for(int i=1;i<=n;i++)
  14. for(int j=1;j<=m;j++)
  15. scanf("%d",&w[i][j]);
  16. for(int k=2;k<=n+m;k++)
  17. for(int i1=1;i1<=n;i1++)
  18. for(int i2=1;i2<=n;i2++)
  19. {
  20. int j1=k-i1,j2=k-i2;
  21. if(j1>=1&&j1<=m&&j2>=1&&j2<=m)
  22. {
  23. int t=w[i1][j1];
  24. if(i1!=i2) t+=w[i2][j2];
  25. f[k][i1][i2]=max(f[k][i1][i2],f[k-1][i1-1][i2-1]+t);
  26. f[k][i1][i2]=max(f[k][i1][i2],f[k-1][i1][i2-1]+t);
  27. f[k][i1][i2]=max(f[k][i1][i2],f[k-1][i1-1][i2]+t);
  28. f[k][i1][i2]=max(f[k][i1][i2],f[k-1][i1][i2]+t);
  29. }
  30. }
  31. printf("%d\n",f[n+m][n][n]);
  32. }
  33. return 0;
  34. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/927128
推荐阅读
相关标签
  

闽ICP备14008679号