zoukankan      html  css  js  c++  java
  • 51Nod1084 矩阵取数问题 V2

    题目看这里

    一个经典的dp题,典型的错误思想就是做两遍

    我们考虑直接做,f[i][j][x][y]表示第一次取道i,j这个位置,第二次到了x,y这个位置

    考虑这个i,j和x,y分别是从哪里转移过来,就可以得到方程

    f[i][j][x][y]=max(f[i-1][j][x-1][y],f[i][j-1][x-1][y],f[i-1][j][x][y-1],f[i][j-1][x][y-1])+v[x][y]+v[i][j]

    这个方程显然有x+y=i+j那么考虑去掉j,y这一维

    令f[k][i][j]表示走了k步,分别走到第i行,第j行的答案,转移可以写成

    f[k][i][j]=max(f[k-1][i][j],f[k-1][i-1][j-1],f[k-1][i-1][j],f[k-1][i][j-1])+s[i][k-i]+s[j][k-j]

    注意如果i=j那么最后那个s[j][k-j]不要加,滚动一下就可以过了

    当然这题也有网络流做法,非常的类似:

    在左上面建一个源点,与(1,1)点连上,容量为2,费用为0。在右下建一个汇点,与(n,m)连上,容量为2,费用为0.
    然后在中间的每个点(i,j),拆成两个点,建立两条边,一条是容量为1,费用为A[i][j]。另一条容量也是1,费用为0。再把左边和上边的点都连上。跑一次费用流就可以了

    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int n,m,f[210][210],s[210][210];
    int main(){
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j) scanf("%d",s[i]+j);
        for(int k=2;k<=m+n;++k) for(int i=n;i;--i) for(int j=n;j;--j)
            f[i][j]=max(max(f[i][j],f[i-1][j-1]),max(f[i-1][j],f[i][j-1]))+s[i][k-i]+(i!=j?s[j][k-j]:0);
        printf("%d
    ",f[n][n]);
    }

  • 相关阅读:
    git 常用命令大全
    iOS UITextView placeHolder占位文字的N种方法实现方法
    ios自定义日期、时间、城市选择器
    zabbix-agent 自定义key
    linux过滤文本
    mysql修改默认存储目录
    git私库搭建
    vmdk,qcow2导入proxmox
    centos字符集问题
    ipset使用
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477097.html
Copyright © 2011-2022 走看看