蓝桥杯-试题ADV-298 算法提高 和谐宿舍2 C++解题
问题描述
我的某室友学过素描,墙上有n张他的作品。这些作品都是宽度为1,高度不定的矩形,从左到右排成一排,且底边在同一水平线上。
宿舍评比就要来了,为了及格,我们决定买不多于m块的矩形木板,把这些作品和谐掉。要求木板也从左到右排成一排,且底边与作品的底边在同一水平线上。在能够把所有作品和谐掉的前提下,我们希望这些木板的面积和最小,问最小面积和。
题图
输入格式
第一行两个数n和m,表示作品数和木板数;
第二行n个数Hi,表示从左到右第i个作品的高度。
输出格式
一行一个数ans,表示答案。
样例输入
5 2
4 2 3 5 4
样例输出
22
数
据规模和约定
对于30%的数据:1<=n,m<=10;
对于100%的数据:1<=n,m<=100,1<=Hi<=10000。
个人分析
题目属于动态规划类型,要求就是将几幅长条形的作品通过不同的相邻的组合方式,使得用来覆盖的矩形木板的面积和最小,毋庸置疑,这其实是由每个组合中最高的作品幅决定的。同时,一定是全部用满m块木板的方式,可以保证用到最少的面积。
所以首先创造一个变量,求出i->j(两边闭区间)幅作品中,作品的最高高度,代码如下:
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
topPicture[i][j] = max(topPicture[i][j-1],pictureHeight[j]);
题目要求:最多共有m块木板,n幅作品,那么设dp[i][j],i代表着纳入组合分类的作品数,j代表着当前可用的木板数,设k为dp[i][j]状态下,可以组合的作品的数目。
则状态转移方程为:状态转移方程:dp[i][j] = min(dp[i][j],dp[i-k][j-1]+k*topPicture[i-k+1][i])
全部代码如下所示:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int Max = 105;
const int INF = 0X7F7F7F7F; //定义的无穷大
int dp[Max][Max];
int pictureHeight[Max] = { 0 };
int topPicture[Max][Max] = { 0 }; //记录i->j区间内,最高的作品高度
int main() {
int m, n; // m->木板数 n->作品数
memset(dp, INF, sizeof(dp));
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> pictureHeight[i];
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
topPicture[i][j] = max(topPicture[i][j-1],pictureHeight[j]);
for (int i = 1; i <= n; i++) { //遍历作品
dp[i][1] = i * topPicture[1][i];
for (int j = 2; j <= m; j++) { //遍历木板数
for (int k = 1; k <= i - j + 1; k++) {
dp[i][j] = min(dp[i][j], dp[i - k][j - 1] + k * topPicture[i - k + 1][i]);
}
}
}
cout << dp[n][m];
return 0;
}