zoukankan      html  css  js  c++  java
  • 双路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
    */
    
  • 相关阅读:
    安装VMware Tools和设置屏幕
    线程
    制作数据集-解析篇
    制作数据集-应用篇
    tf.train.examle函数
    输入手写数字输出识别结果——分析篇
    输入手写数字输出识别结果
    断点续训
    UC972开发板,参考实验8,完成定时器触发信号输出实验
    hz和s和脉冲
  • 原文地址:https://www.cnblogs.com/dream1024/p/13957866.html
Copyright © 2011-2022 走看看