王姐勇闯金字塔
王姐一大早醒来,发现自己居然在金字塔尖上,王姐非常害怕,但是王姐想了一想为了减肥要以最长的路线下金字塔以达到锻炼的目的,对于程序猿的王姐来说当然是小菜一碟,此时王姐掏出了笔记本开始写程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的样例中,从7→3→8→7→5 的路径产生了最大
输入格式
第一个行一个正整数 r ,表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
输出格式
单独的一行,包含那个可能得到的最大的和。
输入输出样例
输入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出
30
说明/提示
【数据范围】
对于 100% 的数据,1≤r≤1000,所有输入在 0,100 范围内。
解
对我的这个菜鸟来说,看到题的第一眼我以为是贪心但是我不怎么会啊,但转眼一想这不就是dp嘛,这时我想到了y总讲过的闫式dp大法,突然发现我可以帮王姐写代码了!
首先状态表示fij,集合是所有从顶部到ij的路线,所求目标是最长距离,然后状态计算我们从最后一步入手,对于这道题来说就相当于是比大小
状态转移方程 f[x][y]=max(f[x+1][y],f[x+1][y+1])+a[x][y];(其实不用多讲把)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int a[N][N],r,f[N][N];
int main()
{
cin >> r;
for(int i = 1;i <= r;i++)//输入数据
for(int j = 1;j <= i;j++)
{
cin >> a[i][j];
f[i][j] = a[i][j];
}
for(int i = r-1;i>0;i--){
//从倒数第二排开始
for(int j = 1;j<=i;j++)
{
f[i][j] = max(f[i+1][j],f[i+1][j+1])+a[i][j];
// cout << f[i][j]<<" ";
}
// cout << endl;
}
cout << f[1][1]<<endl;
return 0;
}
当然二维是最好理解的,记得当时的一个大佬家欢讲过做成一维的才算真正的理解了这种dp,一维就相当于一边输入一边比较,在理解上面可能会比较困难。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int n,a[1010],i,j,ans,p;
int main(){
scanf("%d",&n);
for(i=n;i;i--)
for(j=i;j<=n;j++)
scanf("%d",&p),a[j]=max(a[j],a[j+1])+p;
for(i=1;i<=n;i++) ans=max(ans,a[i]);
printf("%d",ans);
return 0;
}//一维
昆昆爱滑雪
题目描述
昆昆喜欢滑雪。这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当昆昆滑到坡底,昆昆不得不再次走上坡或者等待升降机来载你。昆昆想知道在一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
昆昆可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 24-17-16-1(从 24 开始,在 1 结束)。当然 25-24-23-…-3-2-1 更长。事实上,这是最长的一条。
输入格式
输入的第一行为表示区域的二维数组的行数 R和列数 C。下面是 R行,每行有 C个数,代表高度(两个数字之间用 1个空格间隔)。
输出格式
输出区域中最长滑坡的长度。
输入输出样例
输入
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
输出
25
说明/提示
对于 100% 的数据,1≤R,C≤100。
解
关键词:记忆化搜索
不多bb后面标准dfs板子
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const