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

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

+ ?





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;

}

2014年百度之星程序设计大赛 - 资格赛 1004 -- Labyrinth,布布扣,bubuko.com

时间: 2025-01-04 18:48:01

2014年百度之星程序设计大赛 - 资格赛 1004 -- Labyrinth的相关文章

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

# -*- coding: utf-8 -*- """ Created on Fri May 16 17:24:05 2014 @author: lifeix """ #快速排序 import sys import random length = 30 def qsort(arr,left,right): lp = left rp = right if lp == rp:return while True: while arr[lp] >=

2014年百度之星程序设计大赛 - 资格赛 1002 Disk Schedule(双调欧几里得旅行商问题)

Problem Description 有很多从磁盘读取数据的需求,包括顺序读取.随机读取.为了提高效率,需要人为安排磁盘读取.然而,在现实中,这种做法很复杂.我们考虑一个相对简单的场景.磁盘有许多轨道,每个轨道有许多扇区,用于存储数据.当我们想在特定扇区来读取数据时,磁头需要跳转到特定的轨道.具体扇区进行读取操作.为了简单,我们假设磁头可以在某个轨道顺时针或逆时针匀速旋转,旋转一周的时间是360个单位时间.磁头也可以随意移动到某个轨道进行读取,每跳转到一个相邻轨道的时间为400个单位时间,跳转

2014年百度之星程序设计大赛 - 资格赛 1001 Energy Conversion

Energy Conversion Problem Description 魔法师百小度也有遇到难题的时候-- 现在,百小度正在一个古老的石门面前,石门上有一段古老的魔法文字,读懂这种魔法文字需要耗费大量的能量和大量的脑力. 过了许久,百小度终于读懂魔法文字的含义:石门里面有一个石盘,魔法师需要通过魔法将这个石盘旋转X度,以使上面的刻纹与天相对应,才能打开石门. 但是,旋转石盘需要N点能量值,而为了解读密文,百小度的能量值只剩M点了!破坏石门是不可能的,因为那将需要更多的能量.不过,幸运的是,作

2014年百度之星程序设计大赛 资格赛第一题 (longlong)

解题思路: 只要看(A-V)*K 这个公式的更新值是否大于等于A ,大于的话继续循环,否则报错 注意一点,数据会爆int WA代码: #include<stdio.h> int main(){ long long n ,m, v, k; int t; scanf("%d",&t); while(t--){ scanf("%lld%lld%lld%lld",&n,&m,&v,&k); int cnt = 0; whi

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

主要是卡了一下 接下来2题还在做 都有思路 1001 考虑完全就行了 #include <cstdio> #include <cstring> using namespace std; int main() { int T; scanf("%d", &T); while(T--) { __int64 n, m, v, k; scanf("%I64d %I64d %I64d %I64d", &n, &m, &v,

hdu 4825 Xor Sum (建树) 2014年百度之星程序设计大赛 - 资格赛 1003

题目 题意:给n个数,m次询问,每次给一个数,求这n个数里与这个数 异或 最大的数. 思路:建一个类似字典数的数,把每一个数用 32位的0或者1 表示,查找从高位向底位找,优先找不同的,如果没有不同的,就找相同的. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 #define LL l

2014年百度之星程序设计大赛 - 资格赛 第一题 Energy Conversion

Problem Description   魔法师百小度也有遇到难题的时候-- 现在,百小度正在一个古老的石门面前,石门上有一段古老的魔法文字,读懂这种魔法文字需要耗费大量的能量和大量的脑力. 过了许久,百小度终于读懂魔法文字的含义:石门里面有一个石盘,魔法师需要通过魔法将这个石盘旋转X度,以使上面的刻纹与天相对应,才能打开石门. 但是,旋转石盘需要N点能量值,而为了解读密文,百小度的能量值只剩M点了!破坏石门是不可能的,因为那将需要更多的能量.不过,幸运的是,作为魔法师的百小度可以耗费V点能量

2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)

题目链接 分析:打表以后就能发现时卡特兰数, 但是有除法取余. f[i] = f[i-1]*(4*i - 2)/(i+1); 看了一下网上的题解,照着题解写了下面的代码,不过还是不明白,为什么用扩展gcd, 不是用逆元吗.. 网上还有别人的解释,没看懂,贴一下: (a / b) % m = ( a % (m*b)) / b 笔者注:鉴于ACM题目特别喜欢M=1000000007,为质数: 当gcd(b,m) = 1, 有性质: (a/b)%m = (a*b^-1)%m, 其中b^-1是b模m的逆

2014年百度之星程序设计大赛 - 初赛(第二轮)

1001 暴力 #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn = 100100; int ll[maxn], rr[maxn]; struct node { int x, y, bj; }e[maxn]; int main() { int cas = 1; int T; scanf("%d", &T);