动态规划 和谐宿舍 (为什么要和本状态做对比理解)

试题 算法提高 和谐宿舍2

提交此题  

资源限制

时间限制:1.0s   内存限制:256.0MB

问题描述

  我的某室友学过素描,墙上有n张他的作品。这些作品都是宽度为1,高度不定的矩形,从左到右排成一排,且底边在同一水平线上。
  宿舍评比就要来了,为了及格,我们决定买不多于m块的矩形木板,把这些作品和谐掉。要求木板也从左到右排成一排,且底边与作品的底边在同一水平线上。
  在能够把所有作品和谐掉的前提下,我们希望这些木板的面积和最小,问最小面积和。

输入格式

  第一行两个数n和m,表示作品数和木板数;
  第二行n个数Hi,表示从左到右第i个作品的高度。

输出格式

  一行一个数ans,表示答案。

样例输入

5 2
4 2 3 5 4

样例输出

22

#include<iostream>
using namespace std;
int dp[101][101];//用i块木板遮住前j幅画的面积最小值 
int mj[101][101];//保存i~j幅画最大的高度值            
int h[101];//保存每幅画的高度  
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>h[i];
	for(int i=1;i<=n;i++)
		for(int j=i;j<=n;j++)
			mj[i][j]=max(mj[i][j-1],h[j]);//找出i~j幅画的最大高度 
	for(int i=1;i<=n;i++)
		dp[1][i]=mj[1][i]*i;//赋值边界1块板时 
	for(int i=2;i<=m;i++)
		for(int j=1;j<=n;j++)
			if(j<=i)//板数大于画数,每个画用一个板子面积最小 
				for(int m=1;m<=j;m++)
					dp[i][j]+=h[m];
			else
				for(int k=1;j-k>=i-1;k++)//因为不知道前面几个画的分组情况和后几个画为一组面积最小所以需要循环判断
					if(k==1)
							dp[i][j]=dp[i-1][j-k]+mj[j-k+1][j]*k;//第一次赋值,否则直接比较全为0 
					else 
						dp[i][j]=min((dp[i-1][j-k]+mj[j-k+1][j]*k),dp[i][j]);	
	cout<<dp[m][n];
	return 0;
}

备注:此题与平常的二维不同在于,其状态转移方程不能确定是前面的哪一个状态最优,所以需要做一个循环遍历,并不断与自身做对比(下图1为需要循环比较,下图2为可确定具体是前面第几个状态影响)

for(int k=1;j-k>=i-1;k++)//因为不知道前面几个画的分组情况和后几个画为一组面积最小所以需要循环判断
	if(k==1)
			dp[i][j]=dp[i-1][j-k]+mj[j-k+1][j]*k;//第一次赋值,否则直接比较全为0 
	else 
			dp[i][j]=min((dp[i-1][j-k]+mj[j-k+1][j]*k),dp[i][j]);	
if(j==0)
		dp[i][j]=min(dp[i-1][1],dp[i-2][1]);
if(j==1)
		dp[i][j]=min(dp[i-1][0],dp[i-1][1])+a[i];

下加一道题以做对比记忆(上图2原题)

试题 算法提高 秘密行动

提交此题  

资源限制

时间限制:1.0s   内存限制:256.0MB

问题描述

  小D接到一项任务,要求他爬到一座n层大厦的顶端与神秘人物会面。这座大厦有一个神奇的特点,每层的高度都不一样,同时,小D也拥有一项特殊能力,可以一次向上跳跃一层或两层,但是这项能力无法连续使用。已知向上1高度消耗的时间为1,跳跃不消耗时间。由于事态紧急,小D想知道他最少需要多少时间到达顶层。

输入格式

  第一行包含一个整数n,代表楼的高度。

  接下来n行每行一个整数ai,代表i层的楼层高度(ai <= 100)。

输出格式

  输出1行,包含一个整数,表示所需的最短时间。

样例输入

5
3
5
1
8
4

样例输出

1

#include<iostream>
using namespace std;
int dp[10001][2];//0跳 1跑 
int a[10001];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	dp[1][0]=0;
	dp[2][0]=0;
	dp[1][1]=a[1];
	dp[2][1]=a[2];
	for(int i=3;i<=n;i++)
		for(int j=0;j<2;j++)
			{
				if(j==0)
					dp[i][j]=min(dp[i-1][1],dp[i-2][1]);
				if(j==1)
					dp[i][j]=min(dp[i-1][0],dp[i-1][1])+a[i];
			}
	cout<<min(dp[n][0],dp[n][1]);
	return 0;
}

上题状态转移方程,下一状态由前面第几个状态确定是明确的,是与题目1不同之处以,留下文章以做记录。

发布了1 篇原创文章 · 获赞 1 · 访问量 20

猜你喜欢

转载自blog.csdn.net/qq_44443766/article/details/105016013