试题 算法提高 和谐宿舍2
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
我的某室友学过素描,墙上有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。
题解
这题很适合用动态规划来解决,要想最终的面积最小,将大区间分成小区间,那么对每
一个子区间处理的时候,也要确保其是最优的,满足最优子结构。
状态的设计: dp[L][R][num] 表示 使用num块木板遮盖第 L 幅画到第 R 幅画 的最小费用。
状态转移方程:dp[L][R][num]=min(height*(i-L+1)+dfs(i+1,R,num-1) , dp[L][R][num]) height是L到R幅画中最高那幅画的高度,i 表示使用一块木板遮盖L到 i 的画。
注意一些剪枝及递归返回条件:
- num>R-L+1 这种情况下,就算每一幅画单独使用一块木板,木板也还会有剩余,这种情况肯定不是最优的解(想想为什么)
- L>R&&num<0 此时木板已经多用了,因此不可能是最优解,返回INF
- L > R&&num == 0 此时正好遮盖所有的画,而且木板用完,是可行解
- dp[L][R][num] != 0 代表之前已经算过这个情况,直接返回dp[L][R][num]
#include<bits/stdc++.h>
using namespace std;
const int INF = 1e8;
const int MAXN = 100 + 1;
int dp[MAXN][MAXN][MAXN];
int he[MAXN];
int N, M;
int ans = INF;;
int dfs(int L, int R, int num) { //使用num 块木板,遮盖L到R幅画
if (num > R - L + 1) //木板多了,肯定不为最优解
return INF;
if (L > R&&num < 0) //已经没有木板了
return INF;
if (L > R&&num == 0) //可行解
return 0;
if (dp[L][R][num] != 0) //已经处理过这种情况了
return dp[L][R][num];
dp[L][R][num] = INF;
int height = 0; //最大的高度
for (int i = L; i <= R; i++) { //依次遮盖L到R幅画,寻找最优解
height = max(height, he[i]);
dp[L][R][num] = min(height*(i - L + 1) + dfs(i + 1, R, num - 1), dp[L][R][num]);
}
return dp[L][R][num];
}
int main() {
memset(dp, 0, sizeof(dp));
memset(he, 0, sizeof(he));
scanf("%d%d", &N, &M);
for (int i = 0; i < N; i++)
scanf("%d", &he[i]);
printf("%d\n", dfs(0, N - 1, M));
return 0;
}
关于这一题,有一篇博客讲得不错,戳这里 https://blog.csdn.net/DO_HACKER/article/details/104291186