动态规划之线性DP

本文介绍了动态规划的概念,并通过一系列问题(如数字迷塔、传球游戏、黑熊过河等)详细阐述了线性DP的应用。文章指出,动态规划能够克服贪心算法无法做到全局最优的缺点,是解决复杂问题的有效方法。同时,文章通过实例解析动态规划的解题思路,帮助读者理解和掌握这一算法。
摘要由CSDN通过智能技术生成

        亲爱的同学们,恭喜你们!你们已经越过C++第一道坎-递归,现在你们迎来的是动态规划——第二道坎。

我们刚刚学的贪心是为线性DP做铺垫的,但是贪心有一个缺点,就是不可以做到全面最优,但DP可以做到。

        动态规划,由前一轮状态退出当前一轮的最优值,这是要记住的。

        版权所有,翻露必究!!!

问题A 探索数字迷塔

Description

晶晶最近迷上了数字迷宫游戏,整天沉浸在一串串看似简单的数字中自得其乐。数字迷宫游戏的魅力体现在变化中隐含着不变的规律,归纳是探究数字迷宫的法宝之一。如图所示,就是一个由线连接起来的数字小方格组成的数字迷塔。

这个迷塔共 n 层,它由 n ×(n + 1)/ 2 个小方格组成。每个小方格中都有一个数字,并且连着下一层的两个小方格。现从塔顶走到塔底,每一步只能走到相邻的方格中,则经过方格的数字之和最大值是多少?这个问题晶晶已经琢磨一天了,她感觉异常棘手。你能帮帮她吗?

Format

Input

输入数据共 n + 1 行,第 1 行是一个整数 n(1 ≤ n ≤ 1000),表示数字迷塔的高度,接下来用 n 行数字表示数字迷塔,其中第 i 行有 i 个正整数,且所有的正整数均不大于 100。

Output

输出可能得到的最大和。

Samples

Sample Input 1

5
9
12 15
10 6 8
2 18 9 5
19 7 10 4 16

Sample Output 1

59

Explanation

样例一说明:

9 → 12 → 10 → 18 → 10

        如果以贪心思想来做,就要考虑到当前最优,那么我们就会9+15+8+9+10,很明显,不是这样的!那么,我们就要考虑全部最优,到两线相交点时,就要打擂台。

阶段-->数字宝塔每一层

状态-->数字宝塔每一层的每一个数

把每个阶段转为下一个阶段时 如何转变的式子-->动态转移方程

本质:枚举(数组记录)

#include<bits/stdc++.h>
using namespace std;
int n,a[1005][1005],dp[1005][1005];
int main() 
{ 	
	cin>>n; 	
	for(int i=1;i<=n;i++) 		
	{
		for(int j=1;j<=i;j++)
		{
			cin>>a[i][j];
		} 
	}
	for(int i=1;i<=n;i++) 		
	{
		dp[n][i]=a[n][i];
	} 
	for(int i=n;i>=1;i--) 	
	{
		for(int j=1;j<i;j++)
		{
			dp[i-1][j]=max(dp[i][j],dp[i][j+1])+a[i-1][j];
		}
	}	
	cout<<dp[1][1];
	return 0;
}

问题B 探索数字迷塔

Description

圣诞特别礼物挂在一棵圣诞树上,这棵树有 n 层,每层有一件礼物,每件礼物都有一个价值,有的礼物还有一些连接线,与下层的礼物相连,领取礼物的规则如下:任选一件礼物,它的下面如果有连接线,则可以继续取它连接的礼物,以此类推,直至取到没有连接线的礼物才结束,你如果是第一个去取,怎样取才能获得最大的价值呢?请你编写一程序解决这一问题。

Format

Input

第一行只有一个数据 n(n ≤ 100),表示有 n 层礼物;

以下有 n 行数据,分别表示第 1 至第 n 层礼物的状态,每行至少由一个数据构成,且第一个数据表示该礼物的价值,后面的数据表示它与哪些层的礼物相连,如果每行只有一个数据则说明这层礼物没有与下层礼物相连,每个数的大小均不超过 10000。

Output

只有一个数,表示获得的最大价值。

Samples

Sample Input 1

3
12 2 3
20
30

Sample Output 1

42

本题输入复杂,需用到字符串。

如果要解释样例,

                   12

             20           30

其中12连着20与30.

#include<bits/stdc++.h>
using namespace std;
int n,a[105][105],s[105],dp[105],ans;
string p;
int main()  
{ 	     
	cin>>n; 	
	getline(cin,p); 	
	for(int i=1;i<=n;i++) 	
	{ 		
		getline(cin,p); 		
		int sum=0; 		
		for(int j=0;j<p.size();j++) 		
		{ 			
			if(p[j]==' ')
			{
				a[i][++s[i]]=sum;
				sum=0;
			}
			if(p[j]>='0'&&p[j]<='9') sum=sum*10+p[j]-'0'; 
		} 	
		a[i][++s[i]]=sum;
	}	 	
	for(int i=n;i>=1;i--)
	{ 		
		dp[i]+=a[i][1]; 		
		int max1=0; 
		for(int j=2;j<=s[i];j++)
		{
			max1=max(max1,dp[a[i][j]]);
		} 				
		dp[i]+=max1; 		
		ans=max(ans,dp[i]); 	
	} 	
	cout<<ans; 	
	return 0;  
}
//aij为第i个层的,连接着j层,i为第几层,j为连接的层数

问题C传球游戏

Description

上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值