R语言编程:阿里推笔试题之一

来源:互联网 发布:excel中vba编程 编辑:程序博客网 时间:2024/06/03 18:04

R语言编程:阿里推笔试题之一

题目

沐哲是一个菜鸟仓库的一个拣货员,但他有非常个怪异的习惯。每次拣货的重量都要比之前拣的一个轻,每次拣到货后都可以得到1块钱,沐哲想知道这样最多能赚多少钱

32 34 7 33 21 2

13 12 3 11 26 36

16 30 22 1 24 14

20 23 25 5 19 29

27 15 9 17 31 4

6 18 8 10 35 28

沐哲可以从仓库的某个货架开始拣货,下一步可以往上走,也可以往下走,当然,向左向右也可以,但必须使得下一个货物重量减小,才会去拣。在上面的仓库中,一条可拣货的路径为 25-22-3。当然30-23-20-16-13-12-3可以拣的货更多。这也是赚钱最多的一条路径.

要求

输入行数、列数和数据矩阵,输出所赚的最大钱数。

例子:

输入:

6 6

32 34 7 33 21 2

13 12 3 11 26 36

16 30 22 1 24 14

20 23 25 5 19 29

27 15 9 17 31 4

6 18 8 10 35 28

 输出:

7

求解过程:

本人想出两张思路来设计程序,不足之处欢迎指出,谢谢!

方法一:暴力求解

说明暴力求解在于求货架上每个元素可以走的最大步数,这里不需要存储每一步的坐标,只要判断基于第k步的所有地址下能否存在第k+1步的地址,则意味着可以走到第k+1步,直至不满足条件为止,此时的k即为最大步数.

函数:

参数说明:

n.row: 表示原始重量矩阵的行数

n.col: 表示原始重量矩阵的列数

start.i: 表示初始货物的横坐标

start.j: 表示初始货物的纵坐标

M:表示初始重量矩阵

Num_Step <- function(n.row, n.col, start.i, start.j, M){   i <- start.i   j <- start.j   s <- 1 # 用于计数   next_step <- list(c(i,j)) # 用于存储第K个节点(s步)可选择的货物坐标(列表)   repeat{     index <- list() #用于存储s步可选择的下一个货物的坐标,满足条件时则赋予给next_step     # 第s步有k个选择,每个选择都意味着下一步的货物位置,该循环基于第s步以寻找第s+1步的位置     for(k in 1:length(next_step)){       i <- next_step[[k]][1] # 提取第k个选择的横坐标       j <- next_step[[k]][2] # 提取第k个选择的纵坐标       # 判断第k个选择的垂直向上的货物是否满足       if(i==1){         next_up <- NA        }else if(M[i,j]>M[i-1,j]){         next_up <- c(i-1,j)       }else{         next_up <- NA       }       # 判断第k个选择的垂直向下的货物是否满足       if(i==n.row){         next_down <- NA       }else if(M[i,j]>M[i+1,j]){         next_down <- c(i+1,j)       }else{         next_down <- NA       }       # 判断第k个选择的水平向左的货物是否满足       if(j==1){         next_left <- NA       }else if(M[i,j]>M[i,j-1]){         next_left <- c(i,j-1)       }else{         next_left <- NA       }       # 判断第k个选择的水平向右的货物是否满足       if(j==n.col){         next_right <- NA       }else if(M[i,j]>M[i,j+1]){         next_right <-  c(i,j+1)       }else{         next_right <- NA       }       # 将第k选择时第s+1步满足条件的位置存储下来       next_id <- list(next_up, next_down, next_left, next_right,NA)       next_id <- next_id[-which(is.na(next_id))] # 剔除空值       # 将所有k各选择的s+1步满足条件的位置存储下来       index <- c(index, next_id)     }     # 判断s+1步是否有效,即从s到s+1步有没有路可走     if(length(index)==0){       break     }     # 如果有路可走,则将s+1步所有的位置信息赋给next_step     next_step <- index     s <- s+1 # 用于计数(步长)   }   return(s) # 这里步长即为货架上以每个货物为初始值时的最大收益 }

测试结果

## 计算所有元素为起始点的最大收益BL_step <- function(n.row, n.col, M){  price <- matrix(NA, n.row, n.col)  for(start.i in 1:n.row){    for(start.j in 1:n.col){     price[start.i,start.j] <- Num_Step(n.row, n.col, start.i, start.j, M)      }  }  return(price)}## 以题目中给的货架为例:M <-matrix(c(32, 34, 7, 33, 21, 2, 13, 12, 3, 11, 26, 36, 16, 30, 22, 1, 24, 14, 20, 23, 25, 5, 19, 29, 27, 15, 9, 17, 31, 4, 6, 18, 8, 10, 35, 28),6,byrow = T) n.row <- nrow(M)print(paste("n.row",n.row, sep = "="))n.row = 6n.col <- ncol(M)print(paste("n.col",n.col, sep = "="))n.col = 6

输出收益矩阵

BL_step(n.row, n.col, M)     [,1] [,2] [,3] [,4] [,5] [,6][1,]    4    5    2    3    2    1[2,]    3    2    1    2    5    6[3,]    4    7    2    1    4    1[4,]    5    6    7    2    3    4[5,]    6    3    2    3    4    1[6,]    1    4    1    2    5    2

方法二:动态规划

说明:利用动态规划的思想,从最大步数最少的元素找起,那么最大步数为s的元素的上下左右四个位置一定存在第s-1步的元素.以此为判断条件结合辅助条件来给矩阵赋值.

算法步骤:

1.令P为一个与初始货架重量矩阵同维度的步数矩阵(初始元素都为0)

2.s=1,即最大步长为1开始

3.矩阵中元素满足上下左右位置的元素都大于该元素,则该元素的最大步长为1

4.从s=2开始,取矩阵中未赋值的元素(即=0的元素),进行逐个判断

5.判断条件1:该元素的上下左右四个元素中至少存在最大步长为(s-1)步的元素

6.判断条件2:若满足判断条件1,则上下左右除去(s-1)元素外,若其余位置比该元素小的元素都已经赋值,也即它只能被进入而不能超其他方向走;或者其余位置都比该元素大时,则该元素即为(s+1)步元素

7.重复3-6步,直至矩阵所以元素都已赋值时结束.

函数及结果

参数说明:

n.row: 初始矩阵的行数

n.col: 初始矩阵的列数

M:初始货架重量矩阵

LP_Step <- function(n.row, n.col, M){    p <- matrix(0, n.row, n.col) # 设置初始收益矩阵   s=1 # 收益为1(s用于计最大步数)   ## 循环第s次,将矩阵元素最多能走的步数等于s步的赋值,直至所有元素填满为止.    repeat{     step_id <- which(p==0, arr.ind = T) # 该步用于取未赋值的元素的位置     temp_step <- c() # 用于存储最大步数为s时的元素的坐标     ## 小循环对s步中未赋值的元素进行判断,是否满足为s+1步元素     for(k in 1:nrow(step_id)){       i <- step_id[k,1]       j <- step_id[k,2]       if(i==1){         up <- NA       }else{         up <- c(i-1, j)       }       if(i==n.row){         down <- NA       }else{         down <- c(i+1, j)       }       if(j==1){         left <- NA       }else{         left <- c(i, j-1)       }       if(j==n.col){         right <- NA       }else{         right <- c(i, j+1)       }       # 将附件的元素的位置存储下来,并取值,取步数值       round_id <- rbind(up, down, left, right,NA)       round_id <- round_id[-which(is.na(round_id), arr.ind = T)[,1],]       round_value <- M[round_id]       round_p <- p[round_id]       id <- which(round_value < M[i,j])# 比该元素小的附近元素的位置       juge_last <- which(round_p==(s-1)) # 取附近最大步数为s-1的元素用于判断        if(length(juge_last)>0){ # 判断条件1         if(s==1){ # 对第一步单独考察           if(M[i,j] <= min(round_value)){             temp_step <- rbind(temp_step,c(i,j))           }         }else if(all(round_p[id]!=0, na.rm = T)){ # 判断条件2           temp_step <- rbind(temp_step,c(i,j))         }                             }     }     p[temp_step] <- s # 对步数矩阵赋值     ## 判断步数矩阵是否都赋值,是则结束,否则继续     if(length(which(p==0))==0){       break     }     s=s+1 # 计步   }   return(p)}M <-matrix(c(32, 34, 7, 33, 21, 2, 13, 12, 3, 11, 26, 36, 16, 30, 22, 1, 24, 14, 20, 23, 25, 5, 19, 29, 27, 15, 9, 17, 31, 4, 6, 18, 8, 10, 35, 28),6,byrow = T) n.row <- nrow(M)n.col <- ncol(M)LP_Step(n.row, n.col, M)     [,1] [,2] [,3] [,4] [,5] [,6][1,]    4    5    2    3    2    1[2,]    3    2    1    2    5    6[3,]    4    7    2    1    4    1[4,]    5    6    7    2    3    4[5,]    6    3    2    3    4    1[6,]    1    4    1    2    5    2
原创粉丝点击