递推 - 计蒜客 - 蒜头君的城堡之旅

蒜国地域是一个 nn 行 mm 列的矩阵,下标均从 11开始。蒜国有个美丽的城堡,在坐标 (n, m)(n,m)上,蒜头君在坐标 (1,1)(1,1) 的位置上。蒜头君打算出发去城堡游玩,游玩结束后返回到起点。在出发去城堡的路上,蒜头君只会选择往下或者往右走,而在返回的路上,蒜头君只会选择往上或者往左走,每次只能走一格。已知每个格子上都有一定数量的蒜味可乐,每个格子至多经过一次。

现在蒜头君请你来帮他计算一下,如何计划来回行程,可以收集到最多的蒜味可乐。

输入格式

第一行输入两个整数 n,m(1 \leq n, m \leq 50)n,m(1n,m50),表示蒜国是一个 nn行 mm 列的矩阵。

接下来输入 nn 行,每行输入 mm 个整数,代表一个 n \times mn×m 的矩阵,每个整数代表对应位置上的蒜味可乐数量,每行的每两个整数之间用一个空格隔开。其中蒜头君的位置和城堡的位置上没有蒜味可乐,用 00 表示,其余位置上的整数范围在 [1,100][1,100] 内。

输出格式

输出一行,输出一个整数,表示蒜头君在来回路上能收集到的蒜味可乐的最大值。

样例输入
3 3
0 2 9
4 8 6
2 7 0
样例输出
36
#include<iostream>
#include<cstring>
using namespace std;
struct pos
{
    int i,j;
    pos(int ii,int jj)
    {
        i = ii;
        j = jj;
    }
};
int n,m;
int mp[51][51];
int dp[51][51][51][51];
bool check(pos a)
{
    return (a.i >= 0 && a.i < n && a.j >= 0 && a.j < m);
}
void init()
{
    memset(dp,-1,sizeof(dp));
    memset(mp,0,sizeof(mp));
}
int work(pos a,pos b)
{
    pos ta = pos(a.i-1,a.j);
    pos tb = pos(a.i,a.j-1);
    pos tc = pos(b.i-1,b.j);
    pos td = pos(b.i,b.j-1);
    bool ca = check(ta),cb = check(tb),cc = check(tc),cd = check(td);
    int ans = -9999999;
    
    if (a.i == 0 && a.j == 0 && b.i == 0 && b.j == 0)   
    {
        return 0;
    }

    if (a.i == b.i && a.j == b.j)
    {
        if (ca && cc)
        {
            if (dp[ta.i][ta.j][tc.i][tc.j] == -1)
            {
                int tp1 = work(ta,tc);
                dp[ta.i][ta.j][tc.i][tc.j] = tp1;
                ans = max(ans,tp1+mp[a.i][a.j]);
            }
            else ans = max(ans,dp[ta.i][ta.j][tc.i][tc.j]+mp[a.i][a.j]);
        }
        if (ca && cd) 
        {
            if (dp[ta.i][ta.j][td.i][td.j] == -1)
            {
                int tp2 = work(ta,tc);
                dp[ta.i][ta.j][td.i][td.j] = tp2;
                ans = max(ans,tp2+mp[a.i][a.j]);
            }
            else ans = max(ans,dp[ta.i][ta.j][td.i][td.j]+mp[a.i][a.j]);
        }
        if (cb && cc) 
        {
            if (dp[tb.i][tb.j][tc.i][tc.j] == -1)
            {
                int tp3 = work(tb,tc);
                dp[tb.i][tb.j][tc.i][tc.j] = tp3;
                ans = max(ans,tp3+mp[a.i][a.j]);
            }
            else ans = max(ans,dp[tb.i][tb.j][tc.i][tc.j]+mp[a.i][a.j]);
        }
        if (cb && cd) 
        {
            if (dp[tb.i][tb.j][td.i][td.j] == -1)
            {
                int tp4 = work(tb,td);
                dp[tb.i][tb.j][td.i][td.j] = tp4;
                ans = max(ans,tp4+mp[a.i][a.j]);
            }
            else ans = max(ans,dp[tb.i][tb.j][td.i][td.j]+mp[a.i][a.j]);
        }
    }
    else
    {
        if (ca && cc)
        {
            if (dp[ta.i][ta.j][tc.i][tc.j] == -1)
            {
                int tp1 = work(ta,tc);
                dp[ta.i][ta.j][tc.i][tc.j] = tp1;
                ans = max(ans,tp1+mp[a.i][a.j]+mp[b.i][b.j]);
            }
            else ans = max(ans,dp[ta.i][ta.j][tc.i][tc.j]+mp[a.i][a.j]+mp[b.i][b.j]);
        }
        if (ca && cd) 
        {
            if (dp[ta.i][ta.j][td.i][td.j] == -1)
            {
                int tp2 = work(ta,tc);
                dp[ta.i][ta.j][td.i][td.j] = tp2;
                ans = max(ans,tp2+mp[a.i][a.j]+mp[b.i][b.j]);
            }
            else ans = max(ans,dp[ta.i][ta.j][td.i][td.j]+mp[a.i][a.j]+mp[b.i][b.j]);
        }
        if (cb && cc) 
        {
            if (dp[tb.i][tb.j][tc.i][tc.j] == -1)
            {
                int tp3 = work(tb,tc);
                dp[tb.i][tb.j][tc.i][tc.j] = tp3;
                ans = max(ans,tp3+mp[a.i][a.j]+mp[b.i][b.j]);
            }
            else ans = max(ans,dp[tb.i][tb.j][tc.i][tc.j]+mp[a.i][a.j]+mp[b.i][b.j]);
        }
        if (cb && cd) 
        {
            if (dp[tb.i][tb.j][td.i][td.j] == -1)
            {
                int tp4 = work(tb,td);
                dp[tb.i][tb.j][td.i][td.j] = tp4;
                ans = max(ans,tp4+mp[a.i][a.j]+mp[b.i][b.j]);
            }
            else ans = max(ans,dp[tb.i][tb.j][td.i][td.j]+mp[a.i][a.j]+mp[b.i][b.j]);
        }
    }
    return ans;
}
int main()
{
    init();
    cin >> n >> m;
    for (int i=0;i<n;i++)
    {
        for (int j=0;j<m;j++)
        {
            cin >> mp[i][j];
        }
    }
    cout << work(pos(n-1,m-1),pos(n-1,m-1));
    return 0;
}
代码写的很长,其中判断那一块可以精简一下,值得关注的还是 check 函数的范围判断以及矩阵多阶段问题的优化,途中这两个人永远处在同一条斜率为 1 的直线上。
通过上面的结论可以极大的优化需要处理的地图点的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值