[动态规划] leetcode 1105 Filling Bookcase Shelves
problem:
类背包。周赛题,比赛时用了记忆搜索,之后学习了一波常规dp做法:
dp[ i ] 代表前i本书的最小高度,每加入一本新书后,我们需要试着把上一层的书放到下面来,看哪种情况高度最小,作为当前结果。
第二个循环逆序是因为我们希望利用上一个大循环里的结果,从高往低读可以避免结果被当前循环覆盖。降低空间复杂度。
class Solution { public: int minHeightShelves(vector<vector<int>>& books, int shelf_width) { int n = books.size(); vector<int> dp(n + 1, 10000000); dp[0] = 0; for(int i = 1; i <= n; i++) { int height = 0; int width = 0; for(int j = i - 1; j >= 0; j--) { height = max(height,books[j][1]); width += books[j][0]; if(width > shelf_width) break; dp[i] = min(dp[i], dp[j] + height); } } return dp[n]; } };
附:比赛期间的代码:
class Solution { public: vector<vector<int>> dp; int result = INT_MAX; int total_width; int dfs(vector<vector<int>>& books,int width,int i,int cur_height) { if(i == books.size()) return 0; if(dp[i][width] != -1) return dp[i][width]; //place in the same layer int new_width = width + books[i][0]; if(new_width <= total_width) { int new_height = 0; if(books[i][1] > cur_height) { new_height = books[i][1] - cur_height; } int r1 = dfs(books, new_width, i + 1, max(cur_height,books[i][1])) + new_height; int r2 = dfs(books, books[i][0], i + 1,books[i][1]) + books[i][1]; return dp[i][width] = min(r1,r2); } else { return dp[i][width] = dfs(books, books[i][0], i + 1,books[i][1]) + books[i][1]; } } int minHeightShelves(vector<vector<int>>& books, int shelf_width) { total_width = shelf_width; dp.resize(1001,vector<int>(1001,-1)); return dfs(books,0,0,0); } };