亲爱的同学们,恭喜你们!你们已经越过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
上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,