Labyrinth

题目链接

Problem Description

度度熊是一只喜欢探险的熊,一次偶然落进了一个m*n矩阵的迷宫,该迷宫只能从矩阵左上角第一个方格开始走,只有走到右上角的第一个格子才算走出迷宫,每一次只能走一格,且只能向上向下向右走以前没有走过的格子,每一个格子中都有一些金币(或正或负,有可能遇到强盗拦路抢劫,度度熊身上金币可以为负,需要给强盗写欠条),度度熊刚开始时身上金币数为0,问度度熊走出迷宫时候身上最多有多少金币?

Input

输入的第一行是一个整数T(T < 200),表示共有T组数据。
每组数据的第一行输入两个正整数m,n(m<=100,n<=100)。接下来的m行,每行n个整数,分别代表相应格子中能得到金币的数量,每个整数都大于等于-100且小于等于100。

Output

对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
每组测试数据输出一行,输出一个整数,代表根据最优的打法,你走到右上角时可以获得的最大金币数目。

Sample Input

2
3 4
1 -1 1 0
2 -2 4 2
3 5 1 -90
2 2
1 1
1 1

Sample Output

Case #1:
18
Case #2:
4

分析

这道题目第一眼看上去就是简单的深搜,按照的深搜的思路做了一遍,超时。后来看的别人的题解是用动态规划做的,对于每个点都可能是从 其上面的 左边的 下面的 走过来的,然后分别保存由这三个方向过来的结果,比较出他们的最大值然后将这个点更新为最大值。注意,一个点不能重复走

代码

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f 
int main()
{
    int t;
    scanf("%d", &t);
    for (int k = 0; k < t; k++)
    {
        int m, n;
        scanf("%d%d", &m, &n);
        int road[m + 1][n + 1];
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
            {
                scanf("%d", &road[i][j]);
            }
        for (int i = 2; i <= m; i++)//把第一列初始化
        {
            road[i][1] += road[i - 1][1];
        }
        int dp1[m + 2], dp2[m + 2];
        for (int i = 2; i <= n; i++)
        {
            dp1[0] = -inf;
            dp2[0] = -inf;
            dp1[m + 1] = -inf;
            dp2[m + 1] = -inf;
            for (int j = m; j >= 1; j--)//由下面的方向走过来的和由左边方向过来的
            {
                dp1[j] = max(dp1[j + 1], road[j][i - 1]) + road[j][i];
            }
            for (int j = 1; j <= m; j++)//从上向下走
            {
                dp2[j] = max(dp2[j - 1], road[j][i - 1]) + road[j][i];
            }
            for (int j = 1; j <= m; j++)
            {
                road[j][i] = max(dp1[j], dp2[j]);//比较出最大值
            }
        }
        printf("Case #%d:\n%d\n", k + 1, road[1][n]);
    }
    return 0;

}
/*
2
3 4
1 -1 1 0
2 -2 4 2
3 5 1 -90
*/

posted @ 2017-04-14 19:04  -梦里不知身是客  阅读(225)  评论(0编辑  收藏  举报