问题描述
我的某室友学过素描,墙上有 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。
题解
动态规划:
f[i][j]
:
集合
:所有用j
块木板覆盖前 i 幅
画的方案的集合属性
:最小值(木板面积之和)
MAX[i][j]
:第 i
块木板 ~ 第 j
块木板的高度最大值
#include <iostream>
using namespace std;
const int N = 110, INF = 0x3f3f3f3f;
int f[N][N];
int h[N], MAX[N][N];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i ++) cin >> h[i], MAX[i][i] = h[i];
for (int i = 1; i < n; i ++)
for (int j = i + 1; j <= n; j ++)
MAX[i][j] = max(MAX[i][j - 1], h[j]);
for (int i = 1; i <= n; i ++)
{
f[i][1] = i * MAX[1][i]; // 只有一块木板
for (int j = 2; j <= m && j <= i; j ++)
{
f[i][j] = INF;
for (int k = 1; k <= i - j + 1; k ++) // j - 1 <= i - k
f[i][j] = min(f[i][j], f[i - k][j - 1] + k * MAX[i - k + 1][i]);
}
}
cout << f[n][m] << endl;
return 0;
}