hdu 1078(记忆化搜索)

  
  
  
  
题意:
老鼠每次最多走k步停下来,停下的这个位置只能比上一个停留的位置大,并获取其价值,每次只能水平或垂直走,问最大能得到的价值
解题思路:这道题可以用记忆化搜索解决,dp[i][j]表示老鼠在位置(i,j)时可以达到的最优值。因为dp的状态是一个有向无环图,刚开始想会不会走死循环,但是这道题有一个条件:下一个位置比当前位置的值要大,所以说既然能到当前位置,那么之前的位置是不可能再次走到的。记忆化搜索实际上感觉就是在一颗解答树上进行剪枝,应该算是一种搜索的策略。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 100;
int n,k,mat[maxn][maxn],dp[maxn][maxn];
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};

bool check(int x,int y,int newx,int newy)
{
	if(newx < 0 || newx >= n || newy < 0 || newy >= n) return false;
	if(mat[x][y] >= mat[newx][newy]) return false;
	return true;
}

void dfsDP(int x,int y)
{
	if(dp[x][y] != -1) return;
	for(int i = 0; i < 4; i++)  //方向
		for(int j = 1; j <= k; j++) //步数
		{
			int newx = x + j * dir[i][0];
			int newy = y + j * dir[i][1];
			if(check(x,y,newx,newy) == false) continue;
			dfsDP(newx,newy);
			dp[x][y] = max(dp[x][y],mat[x][y] + dp[newx][newy]);
		}
	if(dp[x][y] == -1) dp[x][y] = mat[x][y];
}

int main()
{
	while(scanf("%d%d",&n,&k)!=EOF)
	{
		if(n == -1 && k == -1) break;
		for(int i = 0; i < n; i++)
			for(int j = 0; j < n; j++)
				scanf("%d",&mat[i][j]);
		memset(dp,-1,sizeof(dp));
		dfsDP(0,0);
		printf("%d\n",dp[0][0]);
	}
	return 0;
}


你可能感兴趣的:(dp)