13-机器人的运动范围

         地上有一个m行n列的方格,从坐标[0,0]到坐标[m-1,n-1]。一个机器人从坐标[0,0]的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格[35,37],因为3+5+3+7=18。但它不能进入方格[35,38],因为3+5+3+8=19。请问该机器人能够到达多少个格子? 如输入:m = 2, n = 3, k = 1 ,输出:3;输入m = 38,n = 15,k = 9,输出:135

        花了一整天的时间来研究这道题,刚开始的时候只考虑到格子的行和列坐标之和要小于或等于k,设计了一个算法代码如下。运行程序之后才发现,题干还要求行或列的数字的数位之和小于或等于k,这也就意味着数据不准确。

        if(m>=k+1 && n>=k+1) {
        	  return count = (1+k+1)*(k+1)/2;
          }else if(m<k+1 && n>=k+1) {
        	  return count = (k-m+1+k)*m/2;
          }else if(m>=k+1 && n<k+1) {
        	  return count = n*(n-1)/2+n*n;
          }else {
        	  return m*n;
          }

        考虑到要计算行和列的数位之和,则要计算m和n的数位的和,具体计算过程见代码的getValue方法。逐行从左到右对数据进行遍历,当遍历到第i行时,如果i的数位之和大于k,则后面的行不需要再遍历了,因为每次移动只能向左、右、上、下遍历,所以这一行的数据肯定是不可达的。定义一个数组subArray[n],用来记录上次遍历行的节点是否可达。定义dp[n]数组来表示当前行遍历的情况,如果可达则将值设为1,否则为0。遍历完成后将dp复制给subArray。定义一个boolean变量flag,用来记录同一行左边相邻节点是否可达,如果某节点可达则为true。在[0,n-1]范围之类假设遍历到第i行,对列从左到右进行遍历,遍历到某个j节点时,如果i和j的数位之和比k小,同时该节点的左节点或者上节点是可达的,则该节点肯定可达,将节点数count+1,同时设置dp[j] = 1,flag = true;如果该节点是不可达的,则设flag=false。继续遍历j节点的下一个节点。这里面需要继续遍历j节点的原因就是要想到达j+1节点,是有两条路径的,从左边进入或者从上边进入。只有两个条件均不满足时,才不会进入该节点。

package leecodeOff;
/*
 * 13 机器人的运动范围
 * 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 
 * 	一个机器人从坐标 [0, 0] 的格子开始移动,
 * 	它每次可以向左、右、上、下移动一格(不能移动到方格外),
 * 	也不能进入行坐标和列坐标的数位之和大于k的格子。
 * 	例如,当k为18时,机器人能够进入方格 [35, 37] ,
 * 	因为3+5+3+7=18。但它不能进入方格 [35, 38],
 * 	因为3+5+3+8=19。请问该机器人能够到达多少个格子?
 */
public class Demo13 {
	/*
     * 抓住题干的关键词
     *  1.输入的m,n是一个行从0到m-1,列从0到n-1的二维数组
     * 	1.机器人可以上、下、左、右,移动
     * 	2.不能移到格子外
     * 	3.移到的格子的行坐标和列坐标的数位之和要求大于小于或等于输入的k
     * 	4.机器人起始点位是在0,0
     */
	public int movingCount(int m, int n, int k) {
          int count = 0;
          int[] subArray = new int[n];
          for(int i=0;i<m;i++) {
        	  int tempi = getValue(i);
        	  if(tempi >k) {
        		  break;
        	  }
        	  count = count+1;
        	  int[] dp = new int[n];
        	  dp[0] = 1;
        	  boolean flag = true;
        	  for(int j=1;j<n;j++) {
        		  int tempj = getValue(j);
        		  if(tempi + tempj <=k) {
        			  if(j == 1) {
        				  count++;
        				  dp[j] = 1;
        				  flag = true;
        			  }else {
        				  if(flag || subArray[j] == 1) {
            				  count++;
            				  dp[j]  =  1;
            				  flag =true;
            			  }
        			  }
        		  }else {
        			  flag = false;
        		  }
        	  }
        	  subArray = dp;
        	 // System.out.println(Arrays.toString(dp));
          }
          return count;
    }
	
	public int getValue(int temp) {
		int value = 0;
		if(temp <10) {
			value = temp;
		}else {
			while(temp > 0) {
				value +=temp %10;
				temp = temp /10;
			}
		}
		return value;
	}
	
	public static void main(String args[]) {
		Demo13 demo = new Demo13();
		System.out.println("最终结果:"+demo.movingCount(38, 15, 9));
	}
	
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunny_daily

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值