摘樱桃II

摘樱桃II

“作为一个合格的程序员,理应具有修bug修到凌晨4点的魄力”

戳我查看原题。

题目大意


给定一个矩阵,矩阵中的每个数代表该点的樱桃个数。Robot1、Robot2分别从左上角与右上角出发,每次只能选择向正下方、左下方、右下方三个方向移动去采摘樱桃,到达矩阵的最后一行终止。若Robot1与Robot2到达同一个位置,则只有一个Robot可以获得到该点的樱桃。求Robot1与Robot2所能采摘到的最大樱桃数;

思路

这是一道简单的dfs,直接记忆化暴力搜索!(误

本人采用的是dp;由于R1与R2只能向3个方向前进,所以可以看作简单二维dp板子题的进阶版(板子题链接):统计每一层R1与R2所有可能出现的状态,在每个状态的多种不同的可能值中去取最大值作为该状态的最优解,接着在最后一层中选择樱桃最多的状态输出就能完美解决该问题。

如何记录每一层R1与R2的状态

开一个三维状态数组f[t][i][j],t表示层数,i表示robot1的状态,j表示robot2的状态;

如何推得状态方程

在理想状态下对于某一状态f[t][i][j]的robot1与robot2都有三种不同的来源,以robot1为例:位于第t层(行)第i列的robot1可以由位于第t-1层(行)第i列或第i-1列或第i+1列得到,于是乎我们便可得到f[t][i][j]的上一状态,写作状态方程为:

f[t][i][j]=max(

{f[ t - 1 ][ i ][ j ],f[ t - 1 ][ i - 1 ][ j ],f[ t - 1][ i + 1 ][ j ],

f[ t - 1 ][ i ][ j - 1 ],f[ t - 1 ][ i - 1 ][ j - 1 ],f[ t - 1 ][ i + 1 ][ j - 1 ],

f[ t - 1 ][ i ][ j + 1 ],f[ t - 1 ][ i - 1 ][ j + 1 ],f[ t - 1 ][ i + 1 ][ j + 1 ]})+grid[ t ][ i ] + grid[ t ][ j ];(grid表示该点的樱桃数)

范围问题

对于robot1,若它每次都向右下方前行则i=t,t即为i的上值;同时,我们不难推出robot2与robot1相遇是一个必然会被舍弃的情况,所以i同时也要小于j,既0<i<=min( t , j - 1 );同理我们也可以推出j的取值范围:max( i + 1 , n - t +1 )<=j<=n;

代码

点击查看代码
class Solution {
public:
    int cherryPickup(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size(),rema=0;//rema用来记录达到最后一层时的最大值
        vector<vector<vector<int>>> f(m+1,vector<vector<int>>(n+2, vector<int>(n+2,0)));//建立状态数组,f[t][i][j]中t表示层数,i表示robot1的状态,j表示robot2的状态;
//有关三维vector的初始化有兴趣的可以去了解一下(申桑也是写这个题时才会的……)
        f[1][1][n]=grid[0][0]+grid[0][n-1];//起始状态(第一层)的初始化
        int di[]={1,1,1,0,0,0,-1,-1,-1},dj[]={0,-1,1,0,-1,1,0,-1,1};//定义向量数组,图论常用
        
        for(int t=2;t<=m;t++){//从第二层开始
            for(int i=1;i<min(t+1,n);i++){//注意范围!!!是谁范围写错改了一个多小时我不说(
                for(int j=n;j>max(i,n-t);j--){
                    for(int d=0;d<9;d++){//向量的使用
                        int x=i+di[d],y=j+dj[d];//用xy存储上一状态,也方便检测范围是否合法
                        if(x>0&&x<min(t+1,y)&&y>max(x,n-t)&&y<=n){
                            f[t][i][j]=max(f[t][i][j],f[t-1][x][y]);//先找出最大的上一状态
                        }
                    }
                    f[t][i][j]+=(grid[t-1][i-1]+grid[t-1][j-1]);//加上该状态r1r2的值
                    if(t==m)rema=max(rema,f[t][i][j]);//到达最后一层时开始筛选最大的末状态
                }
            }
        }
        return rema;//返回末状态
    }
};

特殊鸣谢!

@PeachyGalaxy
(多谢万能的学姐教我写博客)
@码字好累申请中译中汉化组
(其实是我自己,码字太累了想吐槽(lll¬ω¬) )

posted @ 2025-01-11 12:47  Xhita  阅读(39)  评论(0)    收藏  举报