蓝桥杯刷题——跳跃(动态规划)

347 阅读2分钟

「这是我参与2022首次更文挑战的第21天,活动详情查看:2022首次更文挑战」。

这是蓝桥杯21年的一道模拟赛,这里用动态规划来解这道题。

题目

image.png

image.png

思路

再来回想一下,动态规划的要点,要将原问题划分为一个个子问题,通过求解简单的子问题来解原问题。那么我们这个大问题如何划分为子问题呢?起点和终点已经给出,终点的答案如何得出?到达终点的前一个点在哪?一共有9种,因为题目共有九种走法,那到达那九个点的前一个点又在哪?也是各又九种,一直往前推,最终可以推到原点。那么只要知道这些点从它们到原点的最大值,我们就可以得到到终点的最大值,也就得出了答案。重点就是通过求解这些简单的子问题最终得出答案。具体做法怎么做呢?一个二维数组存储方格图,另一个二维数组存储在当前方格位子时能有的最大值。再给一个二维数组存放九种走法,最后再写一个判断是否出界的函数,基本布置就已经完成了。再就是设计算法,遍历所有的方格位子,每一次遍历时,都遍历一次九种走法,要判断是否出界,如果不出界,那么就判断存放当前最大值的方格点加上要走的这个方格点的值是否比当前最大方格点的值大,如果大,那么就更新当前最大值的方格点。最后只要输出最后一个方格点就能得出答案了。

代码

#include <bits/stdc++.h>
using namespace std;
int dp[100][100];
int tu[100][100];
int n,m;
int dir[9][2]={{0,1},{0,2},{0,3},{1,0},{1,1},{1,2},{2,0},{2,1},{3,0}};
bool judge(int x,int y){
  if(x>n||y>m)
  return false;
  else
  return true;
}
int max(int x,int y){
  if(x<y)
  return y;
  else 
  return x;
}
int main()
{
  cin>>n>>m;
  for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
      cin>>tu[i][j];
    }
  }
  memset(dp,0,sizeof(dp));
  dp[1][1]=tu[1][1]
  for(int i=1;i<=n;i++)
  {
    for(int j=1;j<=m;j++)
    {
      for(int a=0;a<9;a++){
        int x=i+dir[a][0];
        int y=i+dir[a][1];
        if(judge(x,y))
        {  
          dp[x][y]=max(dp[x][y],dp[i][j]+tu[x][y]);
        }
      }
    }
  }
  cout<<dp[n][m]<<endl;
  return 0;
}