• 双路DP:洛谷P1006 传纸条


    题目

    传送门

    思路

    经典的双路DP,问题看成有两个人,从左上走到右下,除了起点/重点外,路径不重合,求两个人经过的点的权值之和最大值

    设f [p] [i] [j]表示当前走了p步,第一个人走到第i行,第二个人走到第j行,除起点外路径不重合的条件下,权值之和的最大值

    显然,通过p,i,j,我们是可以求出当点两个人的坐标的(因为只能向右或向下走):(i,p-i+1),(j,p-j+1)

    则状态转移:

    [f[p][i][j]=max{^{max{^{f[p-1][i][j]}_{f[p-1][i][j-1]} }_{max{^{f[p-1][i-1][j]}_{f[p-1][i-1][j-1]}}+map[i][p-i+1]+map[j][p-j+1] ]

    特别地,当两个点重合时(i==j)

    [f[p][i][j]=-∞ ]

    代码

    #include <iostream>
    #include <cstdio>
    using namespace std;
    inline int maxx(int a , int b){
    	return a >b ? a : b;
    }
    int n , m;
    int map[60][60];
    int f[120][60][60];
    
    int main() {
    	scanf("%d %d" , &n , &m);
    	for(int i = 1 ; i <= n ; i++)
    		for(int j = 1 ; j <= m ; j++)
    			scanf("%d" , &map[i][j]);
    	f[1][1][1] = map[1][1];
    	for(int p = 2 ; p <= n + m - 1 ; p++)
    		for(int i = 1 ; i <= n && i <= p ; i++)
    			for(int j = 1 ; j <= n && j <= p ; j++) {
    				if(i == 1 && j == 1)continue;
    				f[p][i][j] = maxx(maxx(f[p - 1][i][j] , f[p - 1][i][j - 1]) , maxx(f[p - 1][i - 1][j] , f[p - 1][i - 1][j - 1]));
    				f[p][i][j] += map[i][p - i + 1] + map[j][p - j + 1];
    				if(i == j && p != n + m - 1)//如果到了右下角,两个人是可以重合的
    					f[p][i][j] = -(1 << 29);
    			}
    	cout << f[n + m - 1][n][n];
    	return 0;
    }
    /*
    8 6
    0 94 11 25 24 51 
    15 13 39 67 97 19 
    76 12 33 99 18 92 
    35 74 0 95 71 39 
    33 39 32 37 45 57 
    71 95 5 71 24 86 
    8 51 54 74 24 75 
    70 33 63 29 99 0 
    
    1382
    */
    
  • 相关阅读:
    view上面 长view时候要设置其frame的,
    controller.allowsEditing = NO;神医,
    怎样计算,遗留,
    编码,一点阅读(转:阮一峰的网络日志),
    原来 ascll是对英文系统的编码,
    CoreGraphics 画图,(转燕羽天空)
    Core Graphics,
    计算数据类型占有 字节的长度,
    浅谈Promise(一)
    原生js实现表格内容增删改
  • 原文地址:https://www.cnblogs.com/dream1024/p/13957866.html
Copyright © 2020-2023  润新知