给定一组非负整数组成的数组h,代表一组柱状图的高度,其中每个柱子的宽度都为1。 在这组柱状图中找到能组成的最大矩形的面积(如图所示)。 入参h为一个整型数组,代表每个柱子的高度,返回面积的值。
这个问题和前面我们讲过的一个盛最多水的容器很相似,不同的地方是这个边界可以不为首尾,因为内部也可能存在更大面积的矩形,而那个题目要求以两个边界为前提,组成的容器。上次我准备用dp来解决,没有成功,那是因为原理不符,没有最优子结构。这个问题就可以用dp来解决了。
首先我们来看,存在最优子结构,如果目前存在最大的矩形的面积,再加一个柱子,我们可以判断出加上它,最大的矩形面积。然后这个子问题也是重叠的,在加不加新柱子的问题上,我们判断最大矩形面积的方法是一样的,唯一不同的是边界不同,也就对应的参数不同。另外问题的边界也存在,就是我们输入的这几个高度。子问题的求解也是独立的。
int main() { int n; cin >> n; vector<long> h(n+1); for (int i = 1; i <= n; i++) cin >> h[i]; vector<vector<long>> dp(n+1, vector<long>(n+1)); for (int i = 1; i <= n; i++) dp[i][i] = h[i]; int min_h; // for (int i = n-1; i >= 1; i--) // { //for (int j = i; j <= n; j++) // { // min_h = h[i]; // for (int k = i; k <= j; k++) // min_h = min_h < h[k] ? min_h : h[k]; // dp[i][j] = (min_h *(j - i + 1)) > dp[i][j - 1] ? (min_h *(j - i + 1)) : dp[i][j - 1]; // dp[j][i] = dp[i][j] = dp[i][j] > dp[i + 1][j] ? dp[i][j] : dp[i + 1][j]; // } // } for (int j = 1; j<=n; j++) { for (int i = j-1; i >= 1; i--) { min_h = h[i]; for (int k = i; k <= j; k++) min_h = min_h < h[k] ? min_h : h[k]; dp[i][j] = (min_h *(j - i + 1)) > dp[i][j - 1] ? (min_h *(j - i + 1)) : dp[i][j - 1]; dp[j][i] = dp[i][j] = dp[i][j] > dp[i + 1][j] ? dp[i][j] : dp[i + 1][j]; } } for(int i=0;i<=n;i++) { cout << dp[1][i] << '