有一种游戏是的玩法是这样的:
有一个n*n的格子,每个格子有一个数字。
遵循以下规则:
1. 玩家每次可以由所在格子向上下左右四个方向进行直线移动,每次移动的距离不得超过m
2. 玩家一开始在第一行第一列,并且已经获得该格子的分值
3. 玩家获得每一次移动到的格子的分值
4. 玩家下一次移动到达的格子的分值要比当前玩家所在的格子的分值要大。
5. 游戏所有数字加起来也不大,保证所有数字的和不会超过int型整数的范围
6. 玩家仅能在n*n的格子内移动,超出格子边界属于非法操作
7. 当玩家不能再次移动时,游戏结束
现在问你,玩家所能获得的最大得分是多少?
Input有多组测试数据
每组测试样例第一行是两个整数n,m (1≤n≤100)(1≤m≤100),当n和m都是-1时为程序结束标志,直接退出即可
之后n行,每行n个数字,描述n*n的格子里的数字
Output对于每组测试数据输出一行,这一行仅有一个整数,代表玩家所能获得的最高得分
Sample Input
3 1
1 2 5
10 11 6
12 12 7
-1 -1
Sample Output
37
分析:
一开始用了一个tle的方法:从原点开始神搜,搜一步松弛一下,这样就会导致很多重复的搜索,但是松弛效率并不高(这一条路松了一遍,另外一条路仍然可能再松一遍),就导致超时了。
正解是用dp[i][j]表示从i,j出发所能得到的cheese的最大值,这样遇到非零的dp[i][j]的时候就可以直接用了(因为dp[i][j]已经是最优解了)。
代码:
tle代码:
1 #include <iostream>
2 #include <algorithm>
3 #include <cstring>
4 using namespace std;
5 const int maxn = 110;
6 typedef pair<int, int> PAIR;
7
8 int n, m;
9 int res;
10 int chart[maxn][maxn];
11 int dp[maxn][maxn];
12 PAIR dir[5] = { {0, 0}, {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
13
14 void dfs(int x, int y)
15 {
16 for(int i = 1; i <= m; i++)
17 for (int j = 1; j <= 4; j++)
18 {
19 int xx = x + dir[j].first * i, yy = y + dir[j].second * i;
20 if (xx >= 1 && xx <= n && yy >= 1 && yy <= n && chart[xx][yy] > chart[x][y])
21 {
22 if (dp[xx][yy] < dp[x][y] + chart[xx][yy])
23 {
24 dp[xx][yy] = dp[x][y] + chart[xx][yy];
25 res = max(res, dp[xx][yy]);
26 }
27 dfs(xx, yy);
28 }
29
30 }
31 }
32
33 int main()
34 {
35 while (cin >> n >> m && m != -1 && n != -1)
36 {
37 for (int i = 1; i <= n; i++)
38 for (int j = 1; j <= n; j++)
39 scanf("%d", &chart[i][j]);
40 memset(dp, 0, sizeof(dp));
41 res = 0;
42 dp[1][1] = chart[1][1];
43 dfs(1, 1);
44 cout << res << endl;
45 }
46 }
正解代码:
1 #include <iostream>
2 #include <algorithm>
3 #include <cstring>
4 using namespace std;
5 const int maxn = 110;
6 typedef pair<int, int> PAIR;
7
8 int n, m;
9 int res;
10 int chart[maxn][maxn];
11 int dp[maxn][maxn];
12 PAIR dir[5] = { {0, 0}, {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
13
14 int dfs(int x, int y)
15 {
16 if (!dp[x][y])
17 {
18 int res = 0;
19 for (int i = 1; i <= m; i++)
20 for (int j = 1; j <= 4; j++)
21 {
22 int xx = x + dir[j].first * i, yy = y + dir[j].second * i;
23 if (xx >= 1 && xx <= n && yy >= 1 && yy <= n && chart[xx][yy] > chart[x][y])
24 res = max(res, dfs(xx, yy));
25 }
26 dp[x][y] = chart[x][y] + res;
27 }
28 return dp[x][y];
29 }
30
31 int main()
32 {
33 while (cin >> n >> m && m != -1 && n != -1)
34 {
35 for (int i = 1; i <= n; i++)
36 for (int j = 1; j <= n; j++)
37 scanf("%d", &chart[i][j]);
38 memset(dp, 0, sizeof(dp));
39 cout << dfs(1, 1) << endl;
40 }
41 }