请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。
例如下面的矩阵包含了一条 bfce 路径。
class Solution {
private:
bool dfs(char* matrix, vector<bool> visited, char *str, int x, int y, int rows, int cols )
{
if(x<0||x>=rows||y<0||y>=cols)
return false;
if(matrix[x*cols+y]==*str && visited[x*cols+y]==false)
{
visited[x*cols+y] = true;
if(*(str+1)==0)
return true;
bool res = dfs(matrix,visited,(str+1),x,y-1,rows,cols) ||
dfs(matrix,visited,(str+1),x-1,y,rows,cols) ||
dfs(matrix,visited,(str+1),x,y+1,rows,cols) ||
dfs(matrix,visited,(str+1),x+1,y,rows,cols);
if(res == false)
visited[x*cols+y] = false;
return res;
}
else
return false;
}
public:
bool hasPath(char* matrix, int rows, int cols, char* str)
{
vector<bool> visited(rows*cols,false);
bool res = false;
for(int i = 0;ifor(int j = 0;jreturn res;
}
};
private final static int[][] next = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
private int rows;
private int cols;
public boolean hasPath(char[] array, int rows, int cols, char[] str) {
if (rows == 0 || cols == 0)
return false;
this.rows = rows;
this.cols = cols;
boolean[][] marked = new boolean[rows][cols];
char[][] matrix = buildMatrix(array);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
if (backtracking(matrix, str, marked, 0, i, j))
return true;
return false;
}
private boolean backtracking(char[][] matrix, char[] str, boolean[][] marked, int pathLen, int r, int c) {
if (pathLen == str.length)
return true;
if (r < 0 || r >= rows || c < 0 || c >= cols || matrix[r][c] != str[pathLen] || marked[r][c])
return false;
marked[r][c] = true;
for (int[] n : next)
if (backtracking(matrix, str, marked, pathLen + 1, r + n[0], c + n[1]))
return true;
marked[r][c] = false;
return false;
}
private char[][] buildMatrix(char[] array) {
char[][] matrix = new char[rows][cols];
for (int i = 0, idx = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
matrix[i][j] = array[idx++];
return matrix;
}
地上有一个 m 行和 n 列的方格。一个机器人从坐标 (0, 0) 的格子开始移动,每一次只能向左右上下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于 k 的格子。例如,当 k 为 18 时,机器人能够进入方格(35, 37),因为 3+5+3+7=18。但是,它不能进入方格(35, 38),因为 3+5+3+8=19。请问该机器人能够达到多少个格子?
class Solution {
public:
int movingCount(int threshold, int rows, int cols)
{
bool *flag = new bool[rows * cols];
for(int i = 0; i < rows * cols; i++)
flag[i] = false;
int count = moving(threshold, rows, cols, 0, 0, flag);
return count;
}
int moving(int threshold, int rows, int cols, int i, int j, bool* flag)
{
int count = 0;
if(i >= 0 && i < rows && j >= 0 && j < cols && getsum(i) + getsum(j) <= threshold && flag[i * cols + j] == false)
{
flag[i * cols + j] = true;
count =1 + moving(threshold, rows, cols, i + 1, j, flag)
+ moving(threshold, rows, cols, i - 1, j, flag)
+ moving(threshold, rows, cols, i , j - 1, flag)
+ moving(threshold, rows, cols, i, j + 1, flag);
}
return count;
}
int getsum(int num)
{
int sum = 0;
while(num)
{
sum += num % 10;
num /= 10;
}
return sum;
}
};
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;
}
}
digitSum = new int[rows][cols];
for (int i = 0; i < this.rows; i++)
for (int j = 0; j < this.cols; j++)
digitSum[i][j] = digitSumOne[i] + digitSumOne[j];
}
把一根绳子剪成多段,并且使得每段的长度乘积最大。
For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).
动态规划
public int integerBreak(int n) {
int[] dp = new int[n + 1];
dp[1] = 1;
for (int i = 2; i <= n; i++)
for (int j = 1; j < i; j++)
dp[i] = Math.max(dp[i], Math.max(j * (i - j), dp[j] * (i - j)));
return dp[n];
}
class Solution {
private:
vector<int> memo;
int max3(int a, int b, int c)
{
return max(a,max(b,c));
}
int getMax(int n)
{
if(n == 1)
{
return 1;
}
if(memo[n]!=-1)
return memo[n];
int res = -1;
for(int i =1;ireturn res;
}
public:
int integerBreak(int n) {
memo = vector<int>(n+1,-1);
return getMax(n);
}
};
尽可能多剪长度为 3 的绳子,并且不允许有长度为 1 的绳子出现,如果出现了,就从已经切好长度为 3 的绳子中拿出一段与长度为 1 的绳子重新组合,把它们切成两段长度为 2 的绳子。
证明:当 n >= 5 时,3(n - 3) - 2(n - 2) = n - 5 >= 0。因此把长度大于 5 的绳子切成两段,令其中一段长度为 3 可以使得两段的乘积最大。
public int integerBreak(int n) {
if (n < 2)
return 0;
if (n == 2)
return 1;
if (n == 3)
return 2;
int timesOf3 = n / 3;
if (n - timesOf3 * 3 == 1)
timesOf3--;
int timesOf2 = (n - timesOf3 * 3) / 2;
return (int) (Math.pow(3, timesOf3)) * (int) (Math.pow(2, timesOf2));
}