zoukankan      html  css  js  c++  java
  • dp-棋盘形dp

    luogu类似题很多的。

    P1006 传纸条

    有不少做法。这里提一个三维做法。

    找两条路,可以模拟为有两个人同从(1,1)走到(m,n),走不同的路。

    设有k步,则显然2<=k<m+n (为什么?初始两步,两个人都走上1,1的位置;不多于m+n……)

    因此,f[k][i][j]表示为一个走到第i行,一个走到第j列,总步数k(知道为啥不多于m+n了吧??)

    至于当前位置是由哪个位置来的,显然了好吧。

    看着方程就秒懂了:

    ans=max(f[k][i][j],max(max(f[k-1][i][j],f[k-1][i-1][j]),max(f[k-1][i-1][j-1],f[k-1][i][j-1])));

    对没错恶意压行。。

    可能这样大家看的清楚:

    但是这不全是状态转移方程!!!只是暂时记下一个ans罢了,等号后面是状态转移方程的一部分呢。

        if(ans!=-1)f[k][i][j]=ans+a[k-i][i]+a[k-j][j];

    如果ans有值,我再进行赋值,f[k][i][j]为走到当前的最大值 加上 当前位置能得到的两个值。

    所以要重置f数组为:-1

        初始化f数组:f[2][1][1]=0

    最后输出的为:f[m+n-1][n-1][n] (右下角不会走到,所以是n-1;另外 右下角的左边和上面其实是一样的。输出一种。)

     1 #include <iostream>
     2 #include <cstring>
     3 using namespace std;
     4 int a[100][100],f[2*100][100][100];
     5 int main(){
     6     int m,n,ans; cin>>m>>n; 
     7     memset(f,-1,sizeof(f)), f[2][1][1]=0;
     8     for(int i=1;i<=m;i++)for(int j=1;j<=n;j++)cin>>a[i][j];
     9     for(int k=3;k<m+n;k++)for(int i=1;i<n;i++)for(int j=i+1;j<=n;j++){
    10         ans=max(f[k][i][j],max(max(f[k-1][i][j],f[k-1][i-1][j]),max(f[k-1][i-1][j-1],f[k-1][i][j-1])));
    11         if(ans!=-1)f[k][i][j]=ans+a[k-i][i]+a[k-j][j];
    12     }
    13     cout<<f[m+n-1][n-1][n];
    14 }

     二维做法:

      观察上述做法 我们发现 第一维没有用啊?所以去掉就好了。当然 循环是一样的三层。

      意义不大,节省空间,并未快。

  • 相关阅读:
    TDateTime 的相关用法
    Delphi 2005 之后的版本如何装组件
    (收藏)《博客园精华集》分类索引
    用 IIS 7、ARR 與 Velocity 建设高性能的大型网站
    异常处理准则
    Linq之动态排序(字符传入)
    用存储过程构造一个虚拟日期表发现的趣事
    Linq to SQL 加注Data Annotation在 Asp.Net MVC2中的应用
    .net framework加密方法
    SQL Server到Oracle连接服务器
  • 原文地址:https://www.cnblogs.com/flicker-five/p/10791435.html
Copyright © 2011-2022 走看看