信息学奥赛一本通 2007:【20CSPJ普及组】方格取数 | 洛谷 P7074 [CSP-J2020] 方格取数

【题目链接】

ybt 2007:【20CSPJ普及组】方格取数
洛谷 P7074 [CSP-J2020] 方格取数

【题目考点】

1. 坐标型动规

【解题思路】

  • 确定状态:a[i][j]为从起点走到i,j位置时整数和的最大值
  • 确定状态转移方程:
    • 熊从左上角出发,在第一列范围内只能向下走,可以求出第一列的状态。
    • 从第一列某位置向右走到了第二列,不考虑走到第三列,在这一列中只能一直向上或下一个方向运动,因为不能重复经过已经走过的方格。
      设一维数组u,d,
      u[i]表示到第j列后只向上走,得到的i,j位置的状态a[i][j],
      d[i]表示到第j列后只向下走,得到的i,j位置的状态a[i][j]。
      • 如果只考虑向上走,那么一个位置可能是从左侧或下侧走来的,取其中值更大的状态,u[i] = max(u[i+1], a[i][j-1])
      • 如果只考虑向下走,那么一个位置可能是从左侧或上侧走来的,取其中值更大的状态,d[i] = max(d[i-1], a[i][j-1])
      • 而后比较u[i]与d[i],取其中较大的值,作为a[i][j]。

【注意数据范围】:最大方格数有 1 0 3 ⋅ 1 0 3 = 1 0 6 10^3\cdot10^3 = 10^6 103103=106个,每个格子最大值为 1 0 4 10^4 104,求出总和可能达到 1 0 10 10^{10} 1010,超出了int型表示的范围,因而要用long long类型。

【题解代码】

解法1:
#include<bits/stdc++.h>
using namespace std;
#define N 1005
long long mp[N][N], a[N][N], u[N], d[N];
int main()
{
    int n, m;
    cin>>n>>m;
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            cin>>mp[i][j];
    a[1][1] = mp[1][1];
    for(int i = 2; i <= n; ++i)//求第一列的状态
        a[i][1] = a[i-1][1] + mp[i][1];
    for(int j = 2; j <= m; ++j)//遍历剩下各列
    {
        u[n] = a[n][j-1] + mp[n][j];//生成u数组,从下向上走,如果是最下面一行,只能从左走来。
        for(int i = n - 1; i >= 1; --i)
            u[i] = max(u[i+1], a[i][j-1]) + mp[i][j];//不是最下面一行,可能从左或下方来。
        d[1] = a[1][j-1] + mp[1][j];//生成d数组,从上向下走,如果是最上面一行,只能从左走来
        for(int i = 2; i <= n; ++i)
            d[i] = max(d[i-1], a[i][j-1]) + mp[i][j];//不是最上面一行,可能从左或上方来。
        for(int i = 1; i <= n; ++i)//生成a[i][j]
            a[i][j] = max(u[i], d[i]);
    }
    cout<<a[n][m];
    return 0;
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值