• 方格取数


    问题描述

    设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):
     
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    13
    0
    0
    6
    0
    0
    0
    0
    0
    0
    7
    0
    0
    0
    0
    0
    0
    14
    0
    0
    0
    0
    0
    21
    0
    0
    0
    4
    0
    0
    0
    0
    15
    0
    0
    0
    0
    0
    0
    14
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
    此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。
    输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。
     
    只需输出一个整数,表示2条路径上取得的最大的和。
     
    8
    2 3 13
    2 6 6
    3 5 7
    4 4 14
    5 2 21
    5 6 4
    6 3 15
    7 2 14
    0 0 0
    67
    *********************************************************************
    解析:
        该类型的题我看了很多题解,其中有人是先dfs再动规,但大多数人还是用多线程dp做的,即定义一个三维数组dp[k][i][j](其中k表示走了k步,i表示第一个人在i行,j表示第二个人在j行,这样就可以得出第一个人在k-i+1列,第二个人在k-j+1列)。
    这里为了防止两个人所走路径的混乱交叉,我们规定第2个人走在第1个人的前面,当两个人走到同一个位置时,只加一个方格数的元素,当走到不同的方格时,则加上两个方格的元素。当走到该方格时,每个人最多有两种选择走的这个方格。
    *********************************************************************
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<string>
     4 #include<cstring>
     5 using namespace std;
     6 
     7 int n,num[150][50][50],map[50][50],i,j,k;//变量常量说明
     8 int max(int a,int b)//比较函数
     9 {
    10     return a>b?a:b;
    11 }
    12 int max(int a,int b,int c,int d)//比较函数
    13   {
    14       int m=a;
    15       if(m<b)m=b;
    16       if(m<c)m=c;
    17       if(m<d)m=d;
    18       return m;
    19   }
    20 void init()//初始化函数
    21 {
    22   cin>>n;
    23   memset(map,0,sizeof(map));
    24   while(cin>>i>>j>>k&&i&&j&&k)
    25      {
    26          map[i][j]=k;
    27      }
    28 
    29 
    30 }
    31 void  dp()//dp
    32 {
    33     memset(num,0,sizeof(num));
    34     for(k=1;k<=2*n-1;k++)
    35      for(i=(k<n?0:k+1-n);i<=k&&i<=n;i++)//这里做一下判断,防止列越界
    36       for(j=i;j<=k&&j<=n;j++)//第二个人在第一个人的前方(防止路径交叉)
    37        {
    38          if(i==0&&j==0)num[k][i][j]=num[k-1][i][j];//只有一种选择
    39          else if(i==0&&j==k)num[k][i][j]=num[k-1][i][j-1];//只有一种选择
    40          else if(i==0&&j!=k)num[k][i][j]=max(num[k-1][i][j-1],num[k-1][i][j]);//第二个人有两种选择
    41          else if(i>0&&j==k)num[k][i][j]=max(num[k-1][i-1][j-1],num[k-1][i][j-1]);//第1个人有两种选择
    42          else  num[k][i][j]=max(num[k-1][i-1][j-1],num[k-1][i][j-1],num[k-1][i-1][j],num[k-1][i][j]);//都有两种选择
    43          if(j==i) num[k][i][j]+=map[i][k-i+1];//两人同时走到一个位置
    44          if(j!=i) num[k][i][j]+=map[i][k-i+1]+map[j][k-j+1];//两个走到不同的位置
    45        }
    46     cout<<num[2*n-1][n][n]<<endl;
    47 }
    48 int main()//主函数
    49 {
    50     //freopen("fgqs.in","r",stdin);
    51     //freopen("fgqs.out","w",stdout);
    52     init();
    53     dp();
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    Docker学习笔记
    SpringMVC学习笔记
    机器学习预测2022年考研成绩、考研分数线
    代码随想录贪心算法
    给定两个序列src,dst,src为入栈顺序,判断dst是否为src的一个出栈顺序(c++)
    代码随想录回溯算法
    代码随想录动态规划
    代码随想录二叉树
    Docker安装memcached
    OpenEuler镜像配置
  • 原文地址:https://www.cnblogs.com/sdau--codeants/p/3150813.html
Copyright © 2020-2023  润新知