FatMouse and Cheese

题目描述:

有一种游戏是的玩法是这样的:有一个n*n的格子,每个格子有一个数字。

遵循以下规则:

1. 玩家每次可以由所在格子向上下左右四个方向进行直线移动,每次移动的距离不得超过m

2. 玩家一开始在第一行第一列,并且已经获得该格子的分值

3. 玩家获得每一次移动到的格子的分值

4. 玩家下一次移动到达的格子的分值要比当前玩家所在的格子的分值要大。

5. 游戏所有数字加起来也不大,保证所有数字的和不会超过int型整数的范围

6. 玩家仅能在n*n的格子内移动,超出格子边界属于非法操作

7. 当玩家不能再次移动时,游戏结束

现在问你,玩家所能获得的最大得分是多少?

思路:

dfs+dp,记忆化搜索即可,需要注意的是每次移动不能超过m个长度,但并不是每次移动长度为1就是好的,可能会有负数值,通过长度不超过m的移动可以把负数跳过去不计算

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 110;
int a[N][N];
int dp[N][N];
#define mem(a, b) memset(a, b, sizeof a)
int n, m;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
int dfs(int x, int y){
	if(dp[x][y])return dp[x][y];
	// 每次移动不超过m格
	// 可能会有负值,所以并不是逐格移动最优
	int ans = a[x][y];
	bool f = 0;
	for (int i = 1; i <= m; i++){
		for (int j = 0; j < 4; j++){
			int xx = x + dx[j] * i;
			int yy = y + dy[j] * i;
			if(xx >= 1 && xx <= n && yy >= 1 && yy <= n && a[xx][yy] > a[x][y]){
				ans = max(ans, dfs(xx, yy) + a[x][y]);
			}
		}
	}
	return dp[x][y] = ans;
}
int main()
{
	ios::sync_with_stdio(0);
	while (cin >> n >> m && n != -1 && m != -1){
		for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)cin >> a[i][j];
		mem(dp, 0);
		cout << dfs(1, 1) << "\n";
	}
	return 0;
}

 

posted @ 2020-02-06 16:30  correct  阅读(94)  评论(0)    收藏  举报