【剑指offer】13与14 I
1.面试题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。请问该机器人能够到达多少个格子?
示例 1:
输入:m = 2, n = 3, k = 1
输出:3
示例 2:
输入:m = 3, n = 1, k = 0
输出:1
提示:1 <= n,m <= 100 ,0 <= k <= 20
class Solution {
public:
int movingCount(int m, int n, int k) {
int count = 0;
vector<bool> visit(m*n, 0);
move(0, 0, m, n, k, count, visit);
return count;
}
void move(int x, int y, int m, int n, int k, int &count, vector<bool> &visit){
int idx = x*n+y;
if(x>=m || x<0 || y>=n || y<0 || !sum(x,y,k)|| visit[idx]) return;
count++; visit[idx]=1; //标记访问
//上下左右搜索
move(x+1, y, m, n, k, count, visit);
move(x-1, y, m, n, k, count, visit);
move(x, y+1, m, n, k, count, visit);
move(x, y-1, m, n, k, count, visit);
}
bool sum (int x, int y,int k){
int s=0;
while(x!=0||y!=0){
sum=sum+x%10+y%10;
x=x/10;y=y/10;
}
return s<=k;
}
};
2.面试题14- I. 剪绳子
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m] 。请问 k[0]k[1]…*k[m] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
示例 1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
提示:2 <= n <= 58
思路:1.可将F(n)分解为 1F(n-1), 2F(n-2),…直到F(2)=1,采用递归,每次可将一段绳子剪成两段,剩下的部分可以继续剪,也可不剪 F(n)=max(i*(n-i), i*F(n-i))
class Solution {
public:
int cuttingRope(int n) {
if(n==2) return 1;
if(n==1) return -1;
int r,i;
for(i=1;i<n;i++){
r=max(r,max(i*(n-i),i*cuttingRope(n-i)));
}
return r;
}
};
- 动态规划:
class Solution {
private:
vector<int> dp;
public:
int cuttingRope(int n) {
dp=vector<int>(59,-1);
if(n==2) return 1;
int i,j;
for(i=3;i<=n;i++){
for(j=1;j<i;j++)
dp[i]=max(dp[i],max(j*(i-j),j*dp[i-j]));
}
return dp[n];
}
};