算法提高 和谐宿舍2(动态规划 dfs)

试题 算法提高 和谐宿舍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

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值