牛客 unique-paths
题目描述
一个机器人在m×n大小的地图的左上角(起点,下图中的标记“start"的位置)。
机器人每次向下或向右移动。机器人要到达地图的右下角。(终点,下图中的标记“Finish"的位置)。
可以有多少种不同的路径从起点走到终点?
备注:m和n小于等于100
思路:
代码:
class Solution {
public:
/**
*
* @param m int整型
* @param n int整型
* @return int整型
*/
int uniquePaths(int m, int n) {
// write code here
if(m < 1 || n < 1){
return 0;
}
//申请F(i,j)空间,初始化。F(i,j)表示从(0,0)到当前点的路径数
vector<vector<int>> ret(m,vector<int>(n,1));
for(int i = 1; i < m;++i){
for(int j = 1; j < n; ++j){
//F(i,j)= F(i,j-1) + F(i-1,j),表示到达当前路径数是从左边、上边过来的路径数目的和
ret[i][j] = ret[i-1][j] + ret[i][j-1];
}
}
//返回结果
return ret[m-1][n-1];
}
};
牛客 minimun-path-sum
题目描述
给定一个由非负整数填充的m x n的二维数组,现在要从二维数组的左上角走到右下角,请找出路径上的所有数字之和最小的路径。
注意:你每次只能向下或向右移动。
思路:
和上面的题目相似,初始值、状态转移方程需要作出相应的改变。直接在原来的数组上操作就可以了,不需要另外开辟空间。
代码:
class Solution {
public:
/**
*
* @param grid int整型vector<vector<>>
* @return int整型
*/
int minPathSum(vector<vector<int> >& grid) {
// write code here
//如果为空的话,直接返回0
if(grid.size() == 0){
return 0;
}
//获取行和列的大小
int row = grid.size();
int col = grid[0].size();
//第一行的初始值
for(int i = 1 ;i < col ;++i)
grid[0][i] = grid[0][i-1] + grid[0][i];
//第一列的初始值
for(int i = 1;i < row ;++i)
grid[i][0] = grid[i-1][0] + grid[i][0];
//状态转移方程
for(int i = 1;i< row;++i){
for(int j=1;j<col;++j){
grid[i][j] = min(grid[i][j-1],grid[i-1][j]) + grid[i][j];
}
}
//返回的结果
return grid[row-1][col-1];
}
};
背包问题
有 n 个物品和一个大小为 m 的背包. 给定数组 A 表示每个物品的大小和数组 V 表示每个物品的价值.
问最多能装入背包的总价值是多大?
样例
样例 1:
输入: m = 10, A = [2, 3, 5, 7], V = [1, 5, 2, 4]
输出: 9
解释: 装入 A[1] 和 A[3] 可以得到最大价值, V[1] + V[3] = 9
样例 2:
输入: m = 10, A = [2, 3, 8], V = [2, 5, 8]
输出: 10
解释: 装入 A[0] 和 A[2] 可以得到最大价值, V[0] + V[2] = 10
挑战
O(nm) 空间复杂度可以通过, 不过你可以尝试 O(m) 空间复杂度吗?
注意事项
A[i], V[i], n, m 均为整数
你不能将物品进行切分
你所挑选的要装入背包的物品的总大小不能超过 m
每个物品只能取一次
思路:
代码:
class Solution {
public:
/**
* @param m: An integer m denotes the size of a backpack
* @param A: Given n items with size A[i]
* @param V: Given n items with value V[i]
* @return: The maximum value
*/
int backPackII(int m, vector<int> &A, vector<int> &V) {
// write your code here
if(A.empty() || v.empty || m < 1){
return 0;
}
const int N = A.size + 1;
const int M = m + 1;
vector<vector<int>> result;
result.resize(N);
for(int i = 0; i != N; ++i){
result[i].resize(M,0);
}
for(int i = 1; i < N; ++i){
for(int j = 1; j != M; ++j){
if(A[i-1] > j){
result[i][j] = result[i-1][j];
}
else{
int newvalue = result[i-1][j-A[i-1]] + V[i-1];
result[i][j] = max(newvalue, result[i-1][j]);
}
}
}
return result[N-1][m];
}
};
简练代码:
int knapsack(int W, int N, vector<int>& wt, vector<int>& val) {
// vector 全填入 0,base case 已初始化
vector<vector<int>> dp(N + 1, vector<int>(W + 1, 0));
for (int i = 1; i <= N; i++) {
for (int w = 1; w <= W; w++) {
if (w - wt[i-1] < 0) {
// 当前背包容量装不下,只能选择不装入背包
dp[i][w] = dp[i - 1][w];
} else {
// 装入或者不装入背包,择优
dp[i][w] = max(dp[i - 1][w - wt[i-1]] + val[i-1],
dp[i - 1][w]);
}
}
}
return dp[N][W];
}
优化空间之后的代码:
在这里插入代码片