首页 > 代码库 > 2014年百度之星程序设计大赛 - 资格赛 1004 -- Labyrinth

2014年百度之星程序设计大赛 - 资格赛 1004 -- Labyrinth

Labyrinth

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1453    Accepted Submission(s): 500


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
 
简单dp:可以一列一列的计算,先计算第一列(这个必须从上往下计算),然后计算后面的每一列:
 
  1.枚举每列的元素,并以它为开始位置。
  2.往上计算dp[][]
  3.往下计算dp[][]
以案例为例:
3 4
1 -1 1 0
2 -2 4 2
3 5 1 -90

1 (0 ,0,8) --> 1 8
3 (-2,1,9) --> 3 9
6 (3,6,11) --> 6 11

在此只算两列,后面的和前面一样



+ View Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <cstdio>
#include <cstring>
#define M 105
#define INF 0x0f0f0f0f
using namespace std;
int c[M][M]; // 存每个方格中有多少钱币
int dp[M][M]; // 当前位置当前状态下最多有多少钱币
void clr(int s[][M]){
    for(int i = 0; i < M; i++){
        for(int j = 0; j < M; j++){
            s[i][j] = -INF;
        }
    }
}
inline int max(int a,int b){return a>b?a:b;}
int main()
{
    int t,n,m;
    scanf("%d",&t);
    for(int cas = 1; cas <= t; cas++){
        clr(c);
        clr(dp);
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                scanf("%d",&c[i][j]);
            }
        }
        dp[0][1] = 0;
        for(int i = 1; i <= n; i++){  //计算第一列dp值
            dp[i][1] = dp[i-1][1] + c[i][1];
        }
        int x,y;
        for(int j = 2; j <= m; j++){
            for(int i = 1; i <= n; i++){
 
                x = dp[i][j-1] + c[i][j];  //单独算第一个
                y = x;
                dp[i][j] = max(dp[i][j],x);
 
                for(int k = i-1; k >= 1; k--){  //往上计算
                    x = x + c[k][j];
                    dp[k][j] = max(dp[k][j],x);
                }
 
                for(int k = i+1; k <= n; k++){   //往下计算
                    y = y + c[k][j];
                    dp[k][j] = max(dp[k][j],y);
                }
            }
        }
        printf("Case #%d:\n%d\n",cas,dp[1][m]);
    }
    return 0;
}