摘花生(简单记忆化搜索)

vjudge提交链接

题目:摘花生

——Hello Kitty 想摘点花生送给她喜欢的米老鼠。她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生。Hello Kitty只能向东或向南走,不能向西或向北走。问Hello Kitty 最多能够摘到多少颗花生。
在这里插入图片描述

Input
——第一行是一个整数T,代表一共有多少组数据。1<=T <= 100
接下来是T组数据。
——每组数据的第一行是两个整数,分别代表花生苗的行数R和列数 C ( 1<= R,C <=100)
——每组数据的接下来R行数据,从北向南依次描述每行花生苗的情况。每行数据有 C 个整数,按从西向东的顺序描述了该行每株花生苗上的花生数目 M ( 0<= M <= 1000)。

Output
——对每组输入数据,输出一行,内容为Hello Kitty能摘到得最多的花生颗数。

Sample Input
2
2 2
1 1
3 4
2 3
2 3 4
1 6 5

Sample Output
8
16

解题笔记:

记忆化搜索:
先一条路走到底,当走到不能再走时,说明到底了
那么我们就可以求出终点(tx,ty)前一个点(x,y)可以获得的价值,存放到dp[x][y]中。
注意:当走到不能再走时,返回的是终点对应的dp[][]值,其实是0  


为什么最后输出dfs(1,1)+e[1][1] 

当从终点逐步返回到起点后一个点时
dfs(int x,int y),tx,ty
(x,y)是起点,(tx,ty)是起点的后一个点
dp[x][y]=max(dp[x][y],dfs(tx,ty)+e[tx][ty]);
dfs(tx,ty):表示的值是逐步返回的dp值
e[tx][ty]:表示起点后的一个值

再返回就返回到主函数里面了,e[1][1]自始自终未加过。 

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=110;
int dp[N][N];
int e[N][N];
int to[2][2]={
   
   {0,1},{1,0}};
int R,C;
int dfs(int x,int y)
{
	if(dp[x][y]!=0)
		return dp[x][y];
	int i,tx,ty;
	for(i=0;i<2;i++)
	{
		tx=x+to[i][0];
		ty=y+to[i][1];
		if(tx>=1&&tx<=R&&ty>=1&&ty<=C)
			dp[x][y]=max(dp[x][y],dfs(tx,ty)+e[tx][ty]);//先走一条路,走到终点求终点前一个可以获得多少价值 
		//不使用book标记的原因是,只可以向下和向右走,没有回头路,除了return; 
	}
	return dp[x][y];
}
int main()
{
	int t,i,j;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&R,&C);
		for(i=1;i<=R;i++)
			for(j=1;j<=C;j++)
				scanf("%d",&e[i][j]);
		memset(dp,0,sizeof(dp));	
		printf("%d\n",dfs(1,1)+e[1][1]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Helinshan/article/details/114803549
今日推荐