1 条题解

  • 0
    @ 2024-11-9 19:12:54

    第一种做法是四维dp,这也是最好想的,设 f[i][j][k][l]f[i][j] [k][l] 为从小渊传到小轩的纸条到达 (i,j)(i,j),从小轩传给小渊的纸条到达 (k,l)(k,l) 的路径上取得的最大的好心程度和。

    完全可以换一个思路想,即求从给定的起点出发走到指定位置的两条最短严格不相交路线。

    那么特别显然,转移方程是 $f[i][j] [k][l]=max( f[i][j-1] [k-1][l] , f[i-1][j] [k][l-1] , f[i][j-1] [k][ l-1] , f[i-1][j] [k-1][l] )+a[i][j]+a[k][l]$。

    要小心l的枚举范围,应该是从 j+1j+1mm,只有这样,在枚举第二条路的时候可以控制下标的 ll 不会和 jj 有相等的可能,这样可以保证两条路一定不相交(想一想,为什么)

    由于终点的值是 00,所以目标状态就是f[n][m1],[n1][m]f[n][m-1], [n-1][m]

    如果你不想这样做,那就让 ll 直接从 11 枚举,但需要加一个判断,判断当前的 (i,j)(i,j)(k,l)(k,l) 是不是重合了,如果重合那就把 ff 数组对应的这个地方在转移后减掉一个 a[i][j]a[i][j] 或者 a[k][l]a[k][l]

    原数据比较弱,这个算法时间复杂度是 O(n2m2)O(n^2 * m^2) 的,所以可以过。

    #include <iostream>
    #define maxn 55
    using namespace std;
    int f[maxn][maxn][maxn][maxn],a[maxn][maxn];
    int n,m;
    int max_ele(int a,int b,int c,int d){
        if (b>a)
            a = b;
        if (c>a)
            a = c;
        if (d>a)
            a = d;
        return a;
    }
    int main(){
        cin >> n >> m;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++) 
                    cin >> a[i][j];
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
                for (int k=1;k<=n;k++)
                    for (int l=j+1;l<=m;l++) 
                        f[i][j][k][l]=max_ele(f[i][j-1][k-1][l],f[i-1][j][k][l-1],f[i][j-1][k][l-1],f[i-1][j][k-1][l])+a[i][j]+a[k][l];
        cout << f[n][m-1][n-1][m] << endl;
        return 0;
    }
    
    • 1

    信息

    ID
    133
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    28
    已通过
    15
    上传者