11.剑指Offer-机器人的运动范围

题目描述

地上有一个 m 行和 n 列的方格。一个机器人从坐标 (0, 0) 的格子开始移动,每一次只能向左右上下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于 k 的格子。

例如,当 k 为 18 时,机器人能够进入方格 (35,37),因为 3+5+3+7=18。但是,它不能进入方格 (35,38),因为 3+5+3+8=19。请问该机器人能够达到多少个格子?

private static final int[][] next = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
private int cnt = 0;
private int rows;
private int cols;
private int threshold;
private int[][] digitSum;

public int movingCount(int threshold, int rows, int cols) {
    this.rows = rows;
    this.cols = cols;
    this.threshold = threshold;
    initDigitSum();
    boolean[][] marked = new boolean[rows][cols];
    dfs(marked, 0, 0);
    return cnt;
}

private void dfs(boolean[][] marked, int r, int c) {
    if (r < 0 || r >= rows || c < 0 || c >= cols || marked[r][c])
        return;
    marked[r][c] = true;
    if (this.digitSum[r][c] > this.threshold)
        return;
    cnt++;
    for (int[] n : next)
        dfs(marked, r + n[0], c + n[1]);
}

private void initDigitSum() {
    int[] digitSumOne = new int[Math.max(rows, cols)];
    for (int i = 0; i < digitSumOne.length; i++) {
        int n = i;
        while (n > 0) {
            digitSumOne[i] += n % 10;
            n /= 10;
        }
    }
    this.digitSum = new int[rows][cols];
    for (int i = 0; i < this.rows; i++)
        for (int j = 0; j < this.cols; j++)
            this.digitSum[i][j] = digitSumOne[i] + digitSumOne[j];
}
import java.util.Scanner;

public class RangeOfRobot {

	public static int rows,cols,threshold,count=0;
	public static int[][] next = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
	public static int[][] digitsum;
	public static boolean[][] marked;
	public static int Sum=0;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		threshold=sc.nextInt();
		rows=sc.nextInt();
		cols=sc.nextInt();
		digitsum=new int[rows][cols];
		marked=new boolean[rows][cols];
		if(threshold==0){
			count=0;
		}
		initdigitsum(rows,cols);
		count=movingCount(threshold, rows, cols);
		System.out.println(count);
		
		for(int i=0;i<rows;i++){
			for(int j=0;j<cols;j++){
				System.out.print(marked[i][j]+",");
			}
			System.out.println();
		}
	}
	public static int movingCount(int threshold, int r, int c)
    {
		for(int i=0;i<rows;i++){
			for(int j=0;j<cols;j++){
				Count(threshold,i, j);
			}
		}
		return Sum;
    }
	public static void Count(int threshold, int r, int c)
    {
		if(r<0||r>rows||c<0||c>cols||marked[r][c]||digitsum[r][c]>threshold){
			return;
		}
		marked[r][c]=true;
		Sum++;
		for(int[] step:next){
			movingCount(threshold, r+step[0], c+step[1]);
		}
    }
	
	public static void initdigitsum(int rows, int cols){
		for(int i=0;i<rows;i++){
			int r=sum(i);
			for(int j=0;j<cols;j++){
				digitsum[i][j]=r+sum(j);
			}
		}
	}
	public static int sum(int t){
		int sum=0;
		while(t!=0){
            sum = sum + t % 10;
            t = t / 10;
        }
		return sum;
	}
}
//输入值
7
5 8

//输出值
30
true,true,true,true,true,true,true,true,
true,true,true,true,true,true,true,false,
true,true,true,true,true,true,false,false,
true,true,true,true,true,false,false,false,
true,true,true,true,false,false,false,false,

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值