SWUST OJ 1084 Mzx0821月赛系列之情书

题目:http://acm.swust.edu.cn/problem/1084/

思路:最开始想的是使用dfs,但不知道怎么保证求出一次最短路径的最大保密性之后,求另外一条不相交的路径,后来看了学长的博客之后,每次就两条路径都同步走,只要不是同一个点就不会相交,而且学长用的是双线程dp,我就按照学长的思路,写了这道题。

首先用一个dp[i][j][x][y];来存两条路径的最大保密性的和,

每的点对应的路径就是两个路径的左边和上边的最大值加上当前点的保密性。因为是最短路径,就只能是上边和左边

dp[i][j][x][y]=max(dp[i-1][j][x-1][y],max(dp[i-1][j][x][y-1],max(dp[i][j-1][x-1][y],dp[i][j-1][x][y-1])))+mpt[x][y]+mpt[i][j];

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <queue>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
typedef unsigned long long UL;
#define MS(x,y) memset(x,y,sizeof(x))
#define rpt(i,l,r) for(int i=l;i<=r;i++)
#define rpd(i,r,l) for(int i=r;i>=l;i--)
LL gcd(LL a,LL b){ return b==0?a:gcd(b,a%b);}
#define N 1000005
int n,m;
int mpt[55][55];
int dp[55][55][55][55];
int main(){

    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&mpt[i][j]);
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++){//最好是从1开始,因为后面的x-1,y-1,i-1,j-1存在越界的情况,从1开始就不用考虑了,越界了得值就已经初始化为0了
            for(int j=1;j<=m;j++){
                for(int x=i+1;x<=n;x++)//x=i+1保证始终x,y的那条路径在i,j路径的下面。
                {
                    int y=i+j-x;//因为i+j=x+y; 说明二者的时间是同步的
                    if(y<=0) continue;
                    dp[i][j][x][y]=max(dp[i-1][j][x-1][y],max(dp[i-1][j][x][y-1],max(dp[i][j-1][x-1][y],dp[i][j-1][x][y-1])))+mpt[x][y]+mpt[i][j];
                }
            }
        }
        printf("%d\r\n",dp[n-1][m][n][m-1]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值