洛谷p1732 活蹦乱跳的香穗子 二维DP

Posted ナイト

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷p1732 活蹦乱跳的香穗子 二维DP相关的知识,希望对你有一定的参考价值。

今天不BB了,直接帖原题吧  地址>>https://www.luogu.org/problem/show?pid=1732<<

题目描述

香穗子在田野上调蘑菇!她跳啊跳,发现自己很无聊,于是她想了一个有趣的事情,每个格子最多只能经过1次,且每个格子都有其价值

跳的规则是这样的,香穗子可以向上下左右四个方向跳到相邻的格子,并且她只能往价值更高(这里是严格的大于)的格子跳.

香穗子可以从任意的格子出发,在任意的格子结束,

那么她最多能跳几次?

输入输出格式

输入格式:

第一行n,m,表示田野的长和宽

接下来n行,每行m个数,表示该格的价值

输出格式:

一个数,表示最多跳得次数

输入输出样例

输入样例#1:
2 2
2 5
-1 3
输出样例#1:
2

说明

n,m<=100

这是二维DP样板,是DP中的豪杰,相较普通DP,思路和顺序也有些变化.

这题里,搜索函数是核心内容,建立数学模型也是比较重要(洛谷题解中有多种模型,构建不同也导致他们后续主函数运算部分难易不一,但其实不关键,能写出来就够了)

下面是我构建的搜索函数(疯狂膜洛谷题解大佬):

 

int sgs(int i,int j)
{
    int k=0;
    if(a[i][j]!=-1) return a[i][j];
    if(i-1>=1&&map[i-1][j]<map[i][j]) 
    {
        a[i][j]=max(a[i][j],sgs(i-1,j)+1);
        k=1;
    }
    if(j+1<=m&&map[i][j+1]<map[i][j])
    {
        a[i][j]=max(a[i][j],sgs(i,j+1)+1);
        k=1;
    }
    if(i+1<=n&&map[i+1][j]<map[i][j]) 
    {
        a[i][j]=max(a[i][j],sgs(i+1,j)+1);
        k=1;
    }
    if(j-1>=1&&map[i][j-1]<map[i][j]) 
    {
        a[i][j]=max(a[i][j],sgs(i,j-1)+1);
        k=1;
    }
    if(k==0) a[i][j]=0;
    return a[i][j];
 } 

 

其中map是储存地图数字的数组,a是储存"跳到这个格子的最大次数",对每一个点map[i,j]讨论跳到这个点所需的最大步数,再在主函数中forfor遍历全图就可以找到答案.

函数的查找方法是对该点的上下左右询问,看是否有比该点数字小的点,如果有比他小的(即可从那个点跳到该点),就拿a[i,j]和a[那个点]+1来取最大值.

其中值得注意的一行:

if(a[i][j]!=-1) return a[i][j];
-1是在主函数中输入数据是赋值的.意为"未被询问的",被询问后就会有值(比大于0),依次区分,如果没有这行,那程序的运行会慢好多哦~~~
以下是ac代码:
#include<iostream>
using namespace std;
int max(int a,int b)
{
	return a>b?a:b;
}
int map[101][101],a[101][101];
int n,m;
int sgs(int i,int j)
{
	int k=0;
	if(a[i][j]!=-1) return a[i][j];
	if(i-1>=1&&map[i-1][j]<map[i][j]) 
	{
		a[i][j]=max(a[i][j],sgs(i-1,j)+1);
		k=1;
	}
	if(j+1<=m&&map[i][j+1]<map[i][j])
	{
		a[i][j]=max(a[i][j],sgs(i,j+1)+1);
		k=1;
	}
	if(i+1<=n&&map[i+1][j]<map[i][j]) 
	{
		a[i][j]=max(a[i][j],sgs(i+1,j)+1);
		k=1;
	}
	if(j-1>=1&&map[i][j-1]<map[i][j]) 
	{
		a[i][j]=max(a[i][j],sgs(i,j-1)+1);
		k=1;
	}
	if(k==0) a[i][j]=0;
	return a[i][j];
 } 
int main()
{
	int i,j,way=0;
	cin>>n>>m;
	for(i=1;i<=n;i++)
	for(j=1;j<=m;j++)
	{
		cin>>map[i][j];
		a[i][j]=-1;	
	}
	for(i=1;i<=n;i++)
	for(j=1;j<=m;j++)
	way=max(way,sgs(i,j));
	cout<<way<<endl;
}

  注意边界的判断哦~(比心)


 

以上是关于洛谷p1732 活蹦乱跳的香穗子 二维DP的主要内容,如果未能解决你的问题,请参考以下文章

P1732 活蹦乱跳的香穗子

洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP

题解洛谷P2418 yyy loves OI IV

BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)4

洛谷P1941飞扬的小鸟——细节DP

洛谷P1220关路灯——区间DP